1 \ -*- coding: utf-8 -*-
3 ; -----------------------------------
4 ; PROG100k.f = 76 x RC5toLCD.f
5 ; -----------------------------------
6 ; download source file sized to compile 100 kbytes
7 ; -----------------------------------
9 \ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
10 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
14 \ from scite editor : copy your target selection in (shift+F8) parameter 1:
18 \ drag and drop this file onto SendSourceFileToTarget.bat
19 \ then select your TARGET when asked.
23 \ R4 to R7 must be saved before use and restored after
24 \ scratch registers Y to S are free for use
25 \ under interrupt, IP is free for use
26 \ interrupts reset SR register !
28 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
29 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
31 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
33 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
34 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
36 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
38 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
39 \ ASSEMBLER conditionnal usage before ?JMP ?GOTO : S< S>= U< U>= 0= 0<> 0<
41 \ FORTH conditionnal : 0= 0< = < > U<
43 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
44 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
45 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
47 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
48 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
49 \ without usage of an auxiliary 5V to feed the LCD_Vo
50 \ and without potentiometer to adjust the LCD contrast :
51 \ to adjust LCD contrast, just press S1 (-) or S2 (+)
52 \ LCDVo current consumption ~ 500 uA.
54 \ ===================================================================================
55 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
56 \ ===================================================================================
59 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
61 \ GND <-------+---0V0----------> 1 LCD_Vss
62 \ VCC >------ | --3V6-----+----> 2 LCD_Vdd
69 \ LCD_TIM_.2 >---||--+--^/\/\/v--+----> 3 LCD_Vo (= 0V6 without modulation)
70 \ -------------------------> 4 LCD_RW
71 \ -------------------------> 5 LCD_RW
72 \ -------------------------> 6 LCD_EN
73 \ <------------------------> 11 LCD_DB4
74 \ <------------------------> 12 LCD_DB5
75 \ <------------------------> 13 LCD_DB5
76 \ <------------------------> 14 LCD_DB7
78 \ <----- LCD contrast + <--- Sw1 <--- (finger) :-)
79 \ <----- LCD contrast - <--- Sw2 <--- (finger) :-)
81 \ rc5 <--- OUT IR_Receiver (1 TSOP32236)
83 \ first, we test for downloading driver only if UART TERMINAL target
88 SUB #308,TOS \ FastForth V3.8
90 'CR' EMIT \ return to column 1 without 'LF'
91 ABORT" FastForth V3.8 please!"
92 PWR_STATE \ remove ABORT_UARTI2CS definition before resuming
98 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
100 MARKER {RC5TOLCD} \ restore the state before MARKER definition
101 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
102 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
103 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
104 \ {RC5TOLCD}+14: make room to save previous IR_VEC
106 [UNDEFINED] CONSTANT [IF]
107 \ https://forth-standard.org/standard/core/CONSTANT
108 \ CONSTANT <name> n -- define a Forth CONSTANT
112 MOV TOS,-2(W) \ PFA = n
119 [UNDEFINED] STATE [IF]
120 \ https://forth-standard.org/standard/core/STATE
121 \ STATE -- a-addr holds compiler state
122 STATEADR CONSTANT STATE
126 \ https://forth-standard.org/standard/core/Equal
127 \ = x1 x2 -- flag test x1=x2
134 XOR #-1,TOS \ 1 flag Z = 1
139 [UNDEFINED] IF [IF] \ define IF and THEN
140 \ https://forth-standard.org/standard/core/IF
141 \ IF -- IFadr initialize conditional forward branch
145 MOV &DP,TOS \ -- HERE
146 ADD #4,&DP \ compile one word, reserve one word
147 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
148 ADD #2,TOS \ -- HERE+2=IFadr
152 \ https://forth-standard.org/standard/core/THEN
153 \ THEN IFadr -- resolve forward branch
154 CODE THEN \ immediate
155 MOV &DP,0(TOS) \ -- IFadr
161 [UNDEFINED] ELSE [IF]
162 \ https://forth-standard.org/standard/core/ELSE
163 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
164 CODE ELSE \ immediate
165 ADD #4,&DP \ make room to compile two words
168 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
170 MOV W,TOS \ -- ELSEadr
175 [UNDEFINED] IS [IF] \ define DEFER! and IS
177 \ https://forth-standard.org/standard/core/DEFERStore
178 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
179 CODE DEFER! \ xt2 xt1 --
180 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
185 \ https://forth-standard.org/standard/core/IS
188 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
189 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
190 \ or in a definition : ... ['] U. IS DISPLAY ...
191 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
193 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
197 IF POSTPONE ['] POSTPONE DEFER!
203 [UNDEFINED] >BODY [IF]
204 \ https://forth-standard.org/standard/core/toBODY
205 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
212 \ CODE 20uS \ n -- 8MHz version
213 \ BEGIN \ 4 + 16 ~ loop
214 \ MOV #39,rDOCON \ 39
221 \ MOV #XDOCON,rDOCON \ 2
226 CODE 20_US \ n -- n * 20 us
227 BEGIN \ here we presume that LCD_TIM_IFG = 1...
229 BIT #1,&LCD_TIM_CTL \ 3
230 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
231 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
233 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
238 CODE TOP_LCD \ LCD Sample
239 \ \ if write : %xxxx_WWWW --
240 \ \ if read : -- %0000_RRRR
241 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
242 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
243 0= IF \ write LCD bits pattern
245 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
246 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
249 THEN \ read LCD bits pattern
252 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
253 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
258 CODE LCD_WRC \ char -- Write Char
259 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
261 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
262 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
263 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
264 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
265 COLON \ high level word starts here
266 TOP_LCD 2 20_US \ write high nibble first
270 CODE LCD_WRF \ func -- Write Fonction
271 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
275 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
276 : LCD_HOME $02 LCD_WRF 100 20_us ;
278 \ [UNDEFINED] OR [IF]
280 \ \ https://forth-standard.org/standard/core/OR
281 \ \ C OR x1 x2 -- x3 logical OR
289 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
290 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
291 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
292 \ : LCD_FN_SET $20 OR LCD_WrF ;
293 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
294 \ : LCD_GOTO $80 OR LCD_WrF ;
297 \ CODE LCD_RDS \ -- status Read Status
298 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
299 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
300 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
301 \ COLON \ starts a FORTH word
302 \ TOP_LCD 2 20_us \ -- %0000_HHHH
303 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
304 \ HI2LO \ switch from FORTH to assembler
305 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
306 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
307 \ MOV @RSP+,IP \ restore IP saved by COLON
311 \ CODE LCD_RDC \ -- char Read Char
312 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
317 \ ******************************\
318 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
319 \ ******************************\
320 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
321 BIT.B #SW2,&SW2_IN \ test switch S2
322 0= IF \ case of switch S2 pressed
323 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
325 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
328 BIT.B #SW1,&SW1_IN \ test switch S1 input
329 0= IF \ case of Switch S1 pressed
330 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
332 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
339 \ ******************************\
340 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
341 \ ******************************\
342 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
343 \ ******************************\
344 \ \ in : SR(9)=old Toggle bit memory (ADD on)
345 \ \ SMclock = 8|16|24 MHz
346 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
347 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
348 \ \ SR(9)=new Toggle bit memory (ADD on)
349 \ ******************************\
350 \ RC5_FirstStartBitHalfCycle: \
351 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
352 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
353 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
355 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
356 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
358 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
359 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
361 MOV #1778,X \ RC5_Period * 1us
362 MOV #14,W \ count of loop
364 \ ******************************\
365 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
366 \ ******************************\ |
367 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
368 \ RC5_Compute_3/4_Period: \ |
369 RRUM #1,X \ X=1/2 cycle |
372 ADD X,Y \ Y=3/4 cycle
373 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
375 \ ******************************\
376 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
377 \ ******************************\
378 BIT.B #RC5,&IR_IN \ C_flag = IR bit
379 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
380 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
381 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
382 SUB #1,W \ decrement count loop
383 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
384 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
385 0<> WHILE \ ----> out of loop ----+
386 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
388 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
389 CMP Y,X \ 1 | cycle time out of bound ?
391 BIC #$30,&RC5_TIM_CTL \ | | stop timer
392 GOTO FW1 \ | | quit on truncated RC5 message
394 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
396 REPEAT \ ----> loop back --+ | with X = new RC5_period value
397 \ ******************************\ |
398 \ RC5_SampleEndOf: \ <---------------------+
399 \ ******************************\
400 BIC #$30,&RC5_TIM_CTL \ stop timer
401 \ ******************************\
402 \ RC5_ComputeNewRC5word \
403 \ ******************************\
404 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
405 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
406 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
407 \ ******************************\
409 \ ******************************\
410 BIT #BIT14,T \ test /C6 bit in T
411 0= IF BIS #BIT6,X \ set C6 bit in X
412 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
413 \ ******************************\
414 \ RC5_CommandByteIsDone \ -- BASE RC5_code
415 \ ******************************\
416 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
417 \ ******************************\
418 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
419 XOR @RSP,T \ (new XOR old) Toggle bits
420 BIT #UF10,T \ repeated RC5_command ?
421 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
422 XOR #UF10,0(RSP) \ 5 toggle bit memory
423 \ ******************************\
424 \ Display IR_RC5 code \
425 \ ******************************\
426 SUB #8,PSP \ TOS -- x x x x TOS
427 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
428 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
429 MOV #$10,&BASEADR \ set hexadecimal base
430 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
431 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
432 LO2HI \ switch from assembler to FORTH
433 LCD_CLEAR \ set LCD cursor at home
434 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
435 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
436 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
437 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
438 HI2LO \ -- switch from FORTH to assembler
439 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
440 MOV @PSP+,TOS \ -- TOS
442 MOV @RSP+,SR \ restore SR flags
443 BIC #%1111_1000,SR \ but force CPU Active Mode
444 RET \ (instead of RETI)
448 \ ------------------------------\
449 HDNCODE STOP_R2L \ define new STOP_APP
450 \ ------------------------------\
451 CMP #RET_ADR,&{RC5TOLCD}+8 \
452 0<> IF \ if previous START executing
453 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
454 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
455 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
456 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
457 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
458 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
459 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
460 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
461 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
462 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
467 \ ------------------------------\
469 \ ------------------------------\
470 BW1 \ <-- INI_R2L for some events
472 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
474 ." RC5toLCD is removed,"
475 ." type START to restart"
478 \ ------------------------------\
480 \ ------------------------------\
481 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
482 \ ------------------------------\
484 \ ------------------------------\
485 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
486 \ ------------------------------\
487 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
488 \ ------------------------------\
489 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
490 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
492 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
493 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
495 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
496 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
497 \ CMP #4,TOS \ hardware RST
498 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
499 \ CMP #2,TOS \ Power_ON event
500 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
502 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
504 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
506 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
507 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
508 \ ------------------------------\
509 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
510 \ - - \CNTL Counter lentgh \ 00 = 16 bits
511 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
512 \ -- \ID input divider \ 10 = /4
513 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
514 \ - \TBCLR TimerB Clear
517 \ -------------------------------\
518 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
519 \ -- \CM Capture Mode
524 \ --- \OUTMOD \ 011 = set/reset
530 \ -------------------------------\
532 \ -------------------------------\
534 \ ------------------------------\
535 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
536 \ ------------------------------\
537 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
538 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
539 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
540 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
542 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
543 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
545 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
546 \ ------------------------------\
547 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
548 \ ------------------------------\
549 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
550 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
551 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
552 \ ------------------------------\
553 BIS.B #LCDVo,&LCDVo_DIR \
554 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
555 \ ------------------------------\
556 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
557 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
558 \ ------------------------------\
559 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
560 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
561 \ ******************************\
563 \ ******************************\
564 BIS.B #RC5,&IR_IE \ enable RC5_Int
565 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
566 \ ******************************\
567 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
568 \ ******************************\
569 \ %01 0001 0100 \ TAxCTL
570 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
571 \ -- \ ID divided by 1
572 \ -- \ MC MODE = up to TAxCCRn
573 \ - \ TACLR clear timer count
576 \ ------------------------------\
577 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
578 \ ------------------------------\
580 \ --- \ TAIDEX pre divisor
581 \ ------------------------------\
582 \ %0000 0000 0000 0101 \ TAxCCR0
583 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
584 \ ------------------------------\
585 \ %0000 0000 0001 0000 \ TAxCCTL0
586 \ - \ CAP capture/compare mode = compare
589 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
590 \ ------------------------------\
591 \ define LPM mode for ACCEPT \
592 \ ------------------------------\
593 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
594 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
595 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
596 \ ------------------------------\
598 \ ------------------------------\
600 \ ------------------------------\
601 #1000 20_US \ 1- wait 20 ms
602 %011 TOP_LCD \ 2- send DB5=DB4=1
603 #205 20_US \ 3- wait 4,1 ms
604 %011 TOP_LCD \ 4- send again DB5=DB4=1
605 #5 20_US \ 5- wait 0,1 ms
606 %011 TOP_LCD \ 6- send again again DB5=DB4=1
607 #2 20_US \ wait 40 us = LCD cycle
608 %010 TOP_LCD \ 7- send DB5=1 DB4=0
609 #2 20_US \ wait 40 us = LCD cycle
610 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
611 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
612 LCD_CLEAR \ 10- "LCD_Clear"
613 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
614 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
615 LCD_CLEAR \ 10- "LCD_Clear"
616 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
617 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
618 CR ." I love you" \ display message on LCD
619 ['] CR >BODY IS CR \ CR executes its default value
620 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
621 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
624 \ ------------------------------\
626 \ ------------------------------\
627 CODE START \ this routine replaces WARM and COLD default values by these of this application.
628 \ ------------------------------\
629 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
630 0= IF \ if not done, customizes MARKER_DOES
631 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
632 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
633 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
634 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
635 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
636 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
637 MOV #RC5_INT,&IR_VEC \ init interrupt vector
638 MOV #INI_R2L,PC \ then execute new INI_APP, without return
642 \ ------------------------------\
645 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
647 MARKER {RC5TOLCD} \ restore the state before MARKER definition
648 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
649 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
650 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
651 \ {RC5TOLCD}+14: make room to save previous IR_VEC
653 [UNDEFINED] CONSTANT [IF]
654 \ https://forth-standard.org/standard/core/CONSTANT
655 \ CONSTANT <name> n -- define a Forth CONSTANT
659 MOV TOS,-2(W) \ PFA = n
666 [UNDEFINED] STATE [IF]
667 \ https://forth-standard.org/standard/core/STATE
668 \ STATE -- a-addr holds compiler state
669 STATEADR CONSTANT STATE
673 \ https://forth-standard.org/standard/core/Equal
674 \ = x1 x2 -- flag test x1=x2
681 XOR #-1,TOS \ 1 flag Z = 1
686 [UNDEFINED] IF [IF] \ define IF and THEN
687 \ https://forth-standard.org/standard/core/IF
688 \ IF -- IFadr initialize conditional forward branch
692 MOV &DP,TOS \ -- HERE
693 ADD #4,&DP \ compile one word, reserve one word
694 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
695 ADD #2,TOS \ -- HERE+2=IFadr
699 \ https://forth-standard.org/standard/core/THEN
700 \ THEN IFadr -- resolve forward branch
701 CODE THEN \ immediate
702 MOV &DP,0(TOS) \ -- IFadr
708 [UNDEFINED] ELSE [IF]
709 \ https://forth-standard.org/standard/core/ELSE
710 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
711 CODE ELSE \ immediate
712 ADD #4,&DP \ make room to compile two words
715 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
717 MOV W,TOS \ -- ELSEadr
722 [UNDEFINED] IS [IF] \ define DEFER! and IS
724 \ https://forth-standard.org/standard/core/DEFERStore
725 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
726 CODE DEFER! \ xt2 xt1 --
727 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
732 \ https://forth-standard.org/standard/core/IS
735 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
736 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
737 \ or in a definition : ... ['] U. IS DISPLAY ...
738 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
740 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
744 IF POSTPONE ['] POSTPONE DEFER!
750 [UNDEFINED] >BODY [IF]
751 \ https://forth-standard.org/standard/core/toBODY
752 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
759 \ CODE 20uS \ n -- 8MHz version
760 \ BEGIN \ 4 + 16 ~ loop
761 \ MOV #39,rDOCON \ 39
768 \ MOV #XDOCON,rDOCON \ 2
773 CODE 20_US \ n -- n * 20 us
774 BEGIN \ here we presume that LCD_TIM_IFG = 1...
776 BIT #1,&LCD_TIM_CTL \ 3
777 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
778 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
780 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
785 CODE TOP_LCD \ LCD Sample
786 \ \ if write : %xxxx_WWWW --
787 \ \ if read : -- %0000_RRRR
788 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
789 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
790 0= IF \ write LCD bits pattern
792 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
793 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
796 THEN \ read LCD bits pattern
799 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
800 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
805 CODE LCD_WRC \ char -- Write Char
806 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
808 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
809 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
810 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
811 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
812 COLON \ high level word starts here
813 TOP_LCD 2 20_US \ write high nibble first
817 CODE LCD_WRF \ func -- Write Fonction
818 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
822 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
823 : LCD_HOME $02 LCD_WRF 100 20_us ;
825 \ [UNDEFINED] OR [IF]
827 \ \ https://forth-standard.org/standard/core/OR
828 \ \ C OR x1 x2 -- x3 logical OR
836 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
837 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
838 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
839 \ : LCD_FN_SET $20 OR LCD_WrF ;
840 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
841 \ : LCD_GOTO $80 OR LCD_WrF ;
844 \ CODE LCD_RDS \ -- status Read Status
845 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
846 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
847 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
848 \ COLON \ starts a FORTH word
849 \ TOP_LCD 2 20_us \ -- %0000_HHHH
850 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
851 \ HI2LO \ switch from FORTH to assembler
852 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
853 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
854 \ MOV @RSP+,IP \ restore IP saved by COLON
858 \ CODE LCD_RDC \ -- char Read Char
859 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
864 \ ******************************\
865 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
866 \ ******************************\
867 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
868 BIT.B #SW2,&SW2_IN \ test switch S2
869 0= IF \ case of switch S2 pressed
870 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
872 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
875 BIT.B #SW1,&SW1_IN \ test switch S1 input
876 0= IF \ case of Switch S1 pressed
877 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
879 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
886 \ ******************************\
887 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
888 \ ******************************\
889 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
890 \ ******************************\
891 \ \ in : SR(9)=old Toggle bit memory (ADD on)
892 \ \ SMclock = 8|16|24 MHz
893 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
894 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
895 \ \ SR(9)=new Toggle bit memory (ADD on)
896 \ ******************************\
897 \ RC5_FirstStartBitHalfCycle: \
898 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
899 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
900 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
902 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
903 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
905 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
906 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
908 MOV #1778,X \ RC5_Period * 1us
909 MOV #14,W \ count of loop
911 \ ******************************\
912 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
913 \ ******************************\ |
914 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
915 \ RC5_Compute_3/4_Period: \ |
916 RRUM #1,X \ X=1/2 cycle |
919 ADD X,Y \ Y=3/4 cycle
920 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
922 \ ******************************\
923 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
924 \ ******************************\
925 BIT.B #RC5,&IR_IN \ C_flag = IR bit
926 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
927 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
928 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
929 SUB #1,W \ decrement count loop
930 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
931 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
932 0<> WHILE \ ----> out of loop ----+
933 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
935 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
936 CMP Y,X \ 1 | cycle time out of bound ?
938 BIC #$30,&RC5_TIM_CTL \ | | stop timer
939 GOTO FW1 \ | | quit on truncated RC5 message
941 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
943 REPEAT \ ----> loop back --+ | with X = new RC5_period value
944 \ ******************************\ |
945 \ RC5_SampleEndOf: \ <---------------------+
946 \ ******************************\
947 BIC #$30,&RC5_TIM_CTL \ stop timer
948 \ ******************************\
949 \ RC5_ComputeNewRC5word \
950 \ ******************************\
951 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
952 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
953 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
954 \ ******************************\
956 \ ******************************\
957 BIT #BIT14,T \ test /C6 bit in T
958 0= IF BIS #BIT6,X \ set C6 bit in X
959 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
960 \ ******************************\
961 \ RC5_CommandByteIsDone \ -- BASE RC5_code
962 \ ******************************\
963 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
964 \ ******************************\
965 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
966 XOR @RSP,T \ (new XOR old) Toggle bits
967 BIT #UF10,T \ repeated RC5_command ?
968 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
969 XOR #UF10,0(RSP) \ 5 toggle bit memory
970 \ ******************************\
971 \ Display IR_RC5 code \
972 \ ******************************\
973 SUB #8,PSP \ TOS -- x x x x TOS
974 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
975 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
976 MOV #$10,&BASEADR \ set hexadecimal base
977 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
978 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
979 LO2HI \ switch from assembler to FORTH
980 LCD_CLEAR \ set LCD cursor at home
981 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
982 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
983 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
984 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
985 HI2LO \ -- switch from FORTH to assembler
986 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
987 MOV @PSP+,TOS \ -- TOS
989 MOV @RSP+,SR \ restore SR flags
990 BIC #%1111_1000,SR \ but force CPU Active Mode
991 RET \ (instead of RETI)
995 \ ------------------------------\
996 HDNCODE STOP_R2L \ define new STOP_APP
997 \ ------------------------------\
998 CMP #RET_ADR,&{RC5TOLCD}+8 \
999 0<> IF \ if previous START executing
1000 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
1001 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
1002 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
1003 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
1004 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
1005 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
1006 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
1007 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
1008 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
1009 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
1014 \ ------------------------------\
1016 \ ------------------------------\
1017 BW1 \ <-- INI_R2L for some events
1019 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1021 ." RC5toLCD is removed,"
1022 ." type START to restart"
1025 \ ------------------------------\
1027 \ ------------------------------\
1028 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
1029 \ ------------------------------\
1031 \ ------------------------------\
1032 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
1033 \ ------------------------------\
1034 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
1035 \ ------------------------------\
1036 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
1037 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
1039 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
1040 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
1042 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
1043 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
1044 \ CMP #4,TOS \ hardware RST
1045 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
1046 \ CMP #2,TOS \ Power_ON event
1047 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1049 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
1051 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
1053 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
1054 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
1055 \ ------------------------------\
1056 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1057 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1058 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1059 \ -- \ID input divider \ 10 = /4
1060 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1061 \ - \TBCLR TimerB Clear
1064 \ -------------------------------\
1065 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1066 \ -- \CM Capture Mode
1071 \ --- \OUTMOD \ 011 = set/reset
1077 \ -------------------------------\
1079 \ -------------------------------\
1081 \ ------------------------------\
1082 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1083 \ ------------------------------\
1084 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1085 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1086 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
1087 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1089 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
1090 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1092 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1093 \ ------------------------------\
1094 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1095 \ ------------------------------\
1096 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1097 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1098 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1099 \ ------------------------------\
1100 BIS.B #LCDVo,&LCDVo_DIR \
1101 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1102 \ ------------------------------\
1103 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1104 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1105 \ ------------------------------\
1106 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1107 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1108 \ ******************************\
1110 \ ******************************\
1111 BIS.B #RC5,&IR_IE \ enable RC5_Int
1112 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1113 \ ******************************\
1114 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1115 \ ******************************\
1116 \ %01 0001 0100 \ TAxCTL
1117 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1118 \ -- \ ID divided by 1
1119 \ -- \ MC MODE = up to TAxCCRn
1120 \ - \ TACLR clear timer count
1123 \ ------------------------------\
1124 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1125 \ ------------------------------\
1127 \ --- \ TAIDEX pre divisor
1128 \ ------------------------------\
1129 \ %0000 0000 0000 0101 \ TAxCCR0
1130 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1131 \ ------------------------------\
1132 \ %0000 0000 0001 0000 \ TAxCCTL0
1133 \ - \ CAP capture/compare mode = compare
1136 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1137 \ ------------------------------\
1138 \ define LPM mode for ACCEPT \
1139 \ ------------------------------\
1140 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
1141 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1142 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1143 \ ------------------------------\
1145 \ ------------------------------\
1147 \ ------------------------------\
1148 #1000 20_US \ 1- wait 20 ms
1149 %011 TOP_LCD \ 2- send DB5=DB4=1
1150 #205 20_US \ 3- wait 4,1 ms
1151 %011 TOP_LCD \ 4- send again DB5=DB4=1
1152 #5 20_US \ 5- wait 0,1 ms
1153 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1154 #2 20_US \ wait 40 us = LCD cycle
1155 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1156 #2 20_US \ wait 40 us = LCD cycle
1157 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1158 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1159 LCD_CLEAR \ 10- "LCD_Clear"
1160 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1161 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1162 LCD_CLEAR \ 10- "LCD_Clear"
1163 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1164 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1165 CR ." I love you" \ display message on LCD
1166 ['] CR >BODY IS CR \ CR executes its default value
1167 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1168 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1171 \ ------------------------------\
1173 \ ------------------------------\
1174 CODE START \ this routine replaces WARM and COLD default values by these of this application.
1175 \ ------------------------------\
1176 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
1177 0= IF \ if not done, customizes MARKER_DOES
1178 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
1179 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
1180 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
1181 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
1182 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1183 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
1184 MOV #RC5_INT,&IR_VEC \ init interrupt vector
1185 MOV #INI_R2L,PC \ then execute new INI_APP, without return
1189 \ ------------------------------\
1192 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
1194 MARKER {RC5TOLCD} \ restore the state before MARKER definition
1195 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
1196 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
1197 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
1198 \ {RC5TOLCD}+14: make room to save previous IR_VEC
1200 [UNDEFINED] CONSTANT [IF]
1201 \ https://forth-standard.org/standard/core/CONSTANT
1202 \ CONSTANT <name> n -- define a Forth CONSTANT
1206 MOV TOS,-2(W) \ PFA = n
1213 [UNDEFINED] STATE [IF]
1214 \ https://forth-standard.org/standard/core/STATE
1215 \ STATE -- a-addr holds compiler state
1216 STATEADR CONSTANT STATE
1220 \ https://forth-standard.org/standard/core/Equal
1221 \ = x1 x2 -- flag test x1=x2
1228 XOR #-1,TOS \ 1 flag Z = 1
1233 [UNDEFINED] IF [IF] \ define IF and THEN
1234 \ https://forth-standard.org/standard/core/IF
1235 \ IF -- IFadr initialize conditional forward branch
1239 MOV &DP,TOS \ -- HERE
1240 ADD #4,&DP \ compile one word, reserve one word
1241 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
1242 ADD #2,TOS \ -- HERE+2=IFadr
1246 \ https://forth-standard.org/standard/core/THEN
1247 \ THEN IFadr -- resolve forward branch
1248 CODE THEN \ immediate
1249 MOV &DP,0(TOS) \ -- IFadr
1255 [UNDEFINED] ELSE [IF]
1256 \ https://forth-standard.org/standard/core/ELSE
1257 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
1258 CODE ELSE \ immediate
1259 ADD #4,&DP \ make room to compile two words
1260 MOV &DP,W \ W=HERE+4
1262 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
1264 MOV W,TOS \ -- ELSEadr
1269 [UNDEFINED] IS [IF] \ define DEFER! and IS
1271 \ https://forth-standard.org/standard/core/DEFERStore
1272 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1273 CODE DEFER! \ xt2 xt1 --
1274 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
1279 \ https://forth-standard.org/standard/core/IS
1282 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
1283 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
1284 \ or in a definition : ... ['] U. IS DISPLAY ...
1285 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1287 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1291 IF POSTPONE ['] POSTPONE DEFER!
1297 [UNDEFINED] >BODY [IF]
1298 \ https://forth-standard.org/standard/core/toBODY
1299 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1306 \ CODE 20uS \ n -- 8MHz version
1307 \ BEGIN \ 4 + 16 ~ loop
1308 \ MOV #39,rDOCON \ 39
1315 \ MOV #XDOCON,rDOCON \ 2
1320 CODE 20_US \ n -- n * 20 us
1321 BEGIN \ here we presume that LCD_TIM_IFG = 1...
1323 BIT #1,&LCD_TIM_CTL \ 3
1324 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
1325 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
1327 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
1332 CODE TOP_LCD \ LCD Sample
1333 \ \ if write : %xxxx_WWWW --
1334 \ \ if read : -- %0000_RRRR
1335 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1336 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1337 0= IF \ write LCD bits pattern
1339 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1340 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1343 THEN \ read LCD bits pattern
1346 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1347 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1352 CODE LCD_WRC \ char -- Write Char
1353 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1355 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
1356 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
1357 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1358 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1359 COLON \ high level word starts here
1360 TOP_LCD 2 20_US \ write high nibble first
1364 CODE LCD_WRF \ func -- Write Fonction
1365 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1369 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1370 : LCD_HOME $02 LCD_WRF 100 20_us ;
1372 \ [UNDEFINED] OR [IF]
1374 \ \ https://forth-standard.org/standard/core/OR
1375 \ \ C OR x1 x2 -- x3 logical OR
1383 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
1384 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
1385 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
1386 \ : LCD_FN_SET $20 OR LCD_WrF ;
1387 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
1388 \ : LCD_GOTO $80 OR LCD_WrF ;
1391 \ CODE LCD_RDS \ -- status Read Status
1392 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1393 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1394 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1395 \ COLON \ starts a FORTH word
1396 \ TOP_LCD 2 20_us \ -- %0000_HHHH
1397 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
1398 \ HI2LO \ switch from FORTH to assembler
1399 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
1400 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
1401 \ MOV @RSP+,IP \ restore IP saved by COLON
1405 \ CODE LCD_RDC \ -- char Read Char
1406 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1411 \ ******************************\
1412 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1413 \ ******************************\
1414 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1415 BIT.B #SW2,&SW2_IN \ test switch S2
1416 0= IF \ case of switch S2 pressed
1417 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1419 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1422 BIT.B #SW1,&SW1_IN \ test switch S1 input
1423 0= IF \ case of Switch S1 pressed
1424 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1426 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1433 \ ******************************\
1434 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
1435 \ ******************************\
1436 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1437 \ ******************************\
1438 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1439 \ \ SMclock = 8|16|24 MHz
1440 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1441 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1442 \ \ SR(9)=new Toggle bit memory (ADD on)
1443 \ ******************************\
1444 \ RC5_FirstStartBitHalfCycle: \
1445 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1446 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1447 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1449 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1450 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1452 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
1453 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1455 MOV #1778,X \ RC5_Period * 1us
1456 MOV #14,W \ count of loop
1458 \ ******************************\
1459 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1460 \ ******************************\ |
1461 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1462 \ RC5_Compute_3/4_Period: \ |
1463 RRUM #1,X \ X=1/2 cycle |
1466 ADD X,Y \ Y=3/4 cycle
1467 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1469 \ ******************************\
1470 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1471 \ ******************************\
1472 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1473 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1474 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1475 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1476 SUB #1,W \ decrement count loop
1477 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1478 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1479 0<> WHILE \ ----> out of loop ----+
1480 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1482 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1483 CMP Y,X \ 1 | cycle time out of bound ?
1485 BIC #$30,&RC5_TIM_CTL \ | | stop timer
1486 GOTO FW1 \ | | quit on truncated RC5 message
1488 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1490 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1491 \ ******************************\ |
1492 \ RC5_SampleEndOf: \ <---------------------+
1493 \ ******************************\
1494 BIC #$30,&RC5_TIM_CTL \ stop timer
1495 \ ******************************\
1496 \ RC5_ComputeNewRC5word \
1497 \ ******************************\
1498 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1499 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1500 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1501 \ ******************************\
1502 \ RC5_ComputeC6bit \
1503 \ ******************************\
1504 BIT #BIT14,T \ test /C6 bit in T
1505 0= IF BIS #BIT6,X \ set C6 bit in X
1506 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1507 \ ******************************\
1508 \ RC5_CommandByteIsDone \ -- BASE RC5_code
1509 \ ******************************\
1510 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
1511 \ ******************************\
1512 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1513 XOR @RSP,T \ (new XOR old) Toggle bits
1514 BIT #UF10,T \ repeated RC5_command ?
1515 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
1516 XOR #UF10,0(RSP) \ 5 toggle bit memory
1517 \ ******************************\
1518 \ Display IR_RC5 code \
1519 \ ******************************\
1520 SUB #8,PSP \ TOS -- x x x x TOS
1521 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
1522 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
1523 MOV #$10,&BASEADR \ set hexadecimal base
1524 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
1525 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
1526 LO2HI \ switch from assembler to FORTH
1527 LCD_CLEAR \ set LCD cursor at home
1528 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
1529 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1530 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
1531 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
1532 HI2LO \ -- switch from FORTH to assembler
1533 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
1534 MOV @PSP+,TOS \ -- TOS
1536 MOV @RSP+,SR \ restore SR flags
1537 BIC #%1111_1000,SR \ but force CPU Active Mode
1538 RET \ (instead of RETI)
1542 \ ------------------------------\
1543 HDNCODE STOP_R2L \ define new STOP_APP
1544 \ ------------------------------\
1545 CMP #RET_ADR,&{RC5TOLCD}+8 \
1546 0<> IF \ if previous START executing
1547 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
1548 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
1549 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
1550 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
1551 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
1552 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
1553 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
1554 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
1555 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
1556 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
1561 \ ------------------------------\
1563 \ ------------------------------\
1564 BW1 \ <-- INI_R2L for some events
1566 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1568 ." RC5toLCD is removed,"
1569 ." type START to restart"
1572 \ ------------------------------\
1574 \ ------------------------------\
1575 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
1576 \ ------------------------------\
1578 \ ------------------------------\
1579 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
1580 \ ------------------------------\
1581 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
1582 \ ------------------------------\
1583 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
1584 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
1586 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
1587 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
1589 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
1590 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
1591 \ CMP #4,TOS \ hardware RST
1592 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
1593 \ CMP #2,TOS \ Power_ON event
1594 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1596 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
1598 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
1600 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
1601 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
1602 \ ------------------------------\
1603 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1604 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1605 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1606 \ -- \ID input divider \ 10 = /4
1607 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1608 \ - \TBCLR TimerB Clear
1611 \ -------------------------------\
1612 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1613 \ -- \CM Capture Mode
1618 \ --- \OUTMOD \ 011 = set/reset
1624 \ -------------------------------\
1626 \ -------------------------------\
1628 \ ------------------------------\
1629 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1630 \ ------------------------------\
1631 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1632 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1633 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
1634 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1636 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
1637 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1639 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1640 \ ------------------------------\
1641 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1642 \ ------------------------------\
1643 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1644 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1645 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1646 \ ------------------------------\
1647 BIS.B #LCDVo,&LCDVo_DIR \
1648 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1649 \ ------------------------------\
1650 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1651 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1652 \ ------------------------------\
1653 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1654 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1655 \ ******************************\
1657 \ ******************************\
1658 BIS.B #RC5,&IR_IE \ enable RC5_Int
1659 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1660 \ ******************************\
1661 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1662 \ ******************************\
1663 \ %01 0001 0100 \ TAxCTL
1664 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1665 \ -- \ ID divided by 1
1666 \ -- \ MC MODE = up to TAxCCRn
1667 \ - \ TACLR clear timer count
1670 \ ------------------------------\
1671 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1672 \ ------------------------------\
1674 \ --- \ TAIDEX pre divisor
1675 \ ------------------------------\
1676 \ %0000 0000 0000 0101 \ TAxCCR0
1677 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1678 \ ------------------------------\
1679 \ %0000 0000 0001 0000 \ TAxCCTL0
1680 \ - \ CAP capture/compare mode = compare
1683 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1684 \ ------------------------------\
1685 \ define LPM mode for ACCEPT \
1686 \ ------------------------------\
1687 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
1688 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1689 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1690 \ ------------------------------\
1692 \ ------------------------------\
1694 \ ------------------------------\
1695 #1000 20_US \ 1- wait 20 ms
1696 %011 TOP_LCD \ 2- send DB5=DB4=1
1697 #205 20_US \ 3- wait 4,1 ms
1698 %011 TOP_LCD \ 4- send again DB5=DB4=1
1699 #5 20_US \ 5- wait 0,1 ms
1700 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1701 #2 20_US \ wait 40 us = LCD cycle
1702 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1703 #2 20_US \ wait 40 us = LCD cycle
1704 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1705 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1706 LCD_CLEAR \ 10- "LCD_Clear"
1707 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1708 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1709 LCD_CLEAR \ 10- "LCD_Clear"
1710 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1711 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1712 CR ." I love you" \ display message on LCD
1713 ['] CR >BODY IS CR \ CR executes its default value
1714 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1715 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1718 \ ------------------------------\
1720 \ ------------------------------\
1721 CODE START \ this routine replaces WARM and COLD default values by these of this application.
1722 \ ------------------------------\
1723 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
1724 0= IF \ if not done, customizes MARKER_DOES
1725 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
1726 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
1727 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
1728 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
1729 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1730 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
1731 MOV #RC5_INT,&IR_VEC \ init interrupt vector
1732 MOV #INI_R2L,PC \ then execute new INI_APP, without return
1736 \ ------------------------------\
1739 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
1741 MARKER {RC5TOLCD} \ restore the state before MARKER definition
1742 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
1743 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
1744 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
1745 \ {RC5TOLCD}+14: make room to save previous IR_VEC
1747 [UNDEFINED] CONSTANT [IF]
1748 \ https://forth-standard.org/standard/core/CONSTANT
1749 \ CONSTANT <name> n -- define a Forth CONSTANT
1753 MOV TOS,-2(W) \ PFA = n
1760 [UNDEFINED] STATE [IF]
1761 \ https://forth-standard.org/standard/core/STATE
1762 \ STATE -- a-addr holds compiler state
1763 STATEADR CONSTANT STATE
1767 \ https://forth-standard.org/standard/core/Equal
1768 \ = x1 x2 -- flag test x1=x2
1775 XOR #-1,TOS \ 1 flag Z = 1
1780 [UNDEFINED] IF [IF] \ define IF and THEN
1781 \ https://forth-standard.org/standard/core/IF
1782 \ IF -- IFadr initialize conditional forward branch
1786 MOV &DP,TOS \ -- HERE
1787 ADD #4,&DP \ compile one word, reserve one word
1788 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
1789 ADD #2,TOS \ -- HERE+2=IFadr
1793 \ https://forth-standard.org/standard/core/THEN
1794 \ THEN IFadr -- resolve forward branch
1795 CODE THEN \ immediate
1796 MOV &DP,0(TOS) \ -- IFadr
1802 [UNDEFINED] ELSE [IF]
1803 \ https://forth-standard.org/standard/core/ELSE
1804 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
1805 CODE ELSE \ immediate
1806 ADD #4,&DP \ make room to compile two words
1807 MOV &DP,W \ W=HERE+4
1809 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
1811 MOV W,TOS \ -- ELSEadr
1816 [UNDEFINED] IS [IF] \ define DEFER! and IS
1818 \ https://forth-standard.org/standard/core/DEFERStore
1819 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1820 CODE DEFER! \ xt2 xt1 --
1821 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
1826 \ https://forth-standard.org/standard/core/IS
1829 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
1830 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
1831 \ or in a definition : ... ['] U. IS DISPLAY ...
1832 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1834 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1838 IF POSTPONE ['] POSTPONE DEFER!
1844 [UNDEFINED] >BODY [IF]
1845 \ https://forth-standard.org/standard/core/toBODY
1846 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1853 \ CODE 20uS \ n -- 8MHz version
1854 \ BEGIN \ 4 + 16 ~ loop
1855 \ MOV #39,rDOCON \ 39
1862 \ MOV #XDOCON,rDOCON \ 2
1867 CODE 20_US \ n -- n * 20 us
1868 BEGIN \ here we presume that LCD_TIM_IFG = 1...
1870 BIT #1,&LCD_TIM_CTL \ 3
1871 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
1872 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
1874 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
1879 CODE TOP_LCD \ LCD Sample
1880 \ \ if write : %xxxx_WWWW --
1881 \ \ if read : -- %0000_RRRR
1882 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1883 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1884 0= IF \ write LCD bits pattern
1886 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1887 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1890 THEN \ read LCD bits pattern
1893 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1894 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1899 CODE LCD_WRC \ char -- Write Char
1900 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1902 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
1903 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
1904 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1905 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1906 COLON \ high level word starts here
1907 TOP_LCD 2 20_US \ write high nibble first
1911 CODE LCD_WRF \ func -- Write Fonction
1912 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1916 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1917 : LCD_HOME $02 LCD_WRF 100 20_us ;
1919 \ [UNDEFINED] OR [IF]
1921 \ \ https://forth-standard.org/standard/core/OR
1922 \ \ C OR x1 x2 -- x3 logical OR
1930 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
1931 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
1932 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
1933 \ : LCD_FN_SET $20 OR LCD_WrF ;
1934 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
1935 \ : LCD_GOTO $80 OR LCD_WrF ;
1938 \ CODE LCD_RDS \ -- status Read Status
1939 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1940 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1941 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1942 \ COLON \ starts a FORTH word
1943 \ TOP_LCD 2 20_us \ -- %0000_HHHH
1944 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
1945 \ HI2LO \ switch from FORTH to assembler
1946 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
1947 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
1948 \ MOV @RSP+,IP \ restore IP saved by COLON
1952 \ CODE LCD_RDC \ -- char Read Char
1953 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1958 \ ******************************\
1959 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1960 \ ******************************\
1961 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1962 BIT.B #SW2,&SW2_IN \ test switch S2
1963 0= IF \ case of switch S2 pressed
1964 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1966 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1969 BIT.B #SW1,&SW1_IN \ test switch S1 input
1970 0= IF \ case of Switch S1 pressed
1971 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1973 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1980 \ ******************************\
1981 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
1982 \ ******************************\
1983 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1984 \ ******************************\
1985 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1986 \ \ SMclock = 8|16|24 MHz
1987 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1988 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1989 \ \ SR(9)=new Toggle bit memory (ADD on)
1990 \ ******************************\
1991 \ RC5_FirstStartBitHalfCycle: \
1992 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1993 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1994 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1996 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1997 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1999 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
2000 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2002 MOV #1778,X \ RC5_Period * 1us
2003 MOV #14,W \ count of loop
2005 \ ******************************\
2006 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2007 \ ******************************\ |
2008 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2009 \ RC5_Compute_3/4_Period: \ |
2010 RRUM #1,X \ X=1/2 cycle |
2013 ADD X,Y \ Y=3/4 cycle
2014 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2016 \ ******************************\
2017 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2018 \ ******************************\
2019 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2020 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2021 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2022 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2023 SUB #1,W \ decrement count loop
2024 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2025 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2026 0<> WHILE \ ----> out of loop ----+
2027 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2029 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2030 CMP Y,X \ 1 | cycle time out of bound ?
2032 BIC #$30,&RC5_TIM_CTL \ | | stop timer
2033 GOTO FW1 \ | | quit on truncated RC5 message
2035 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2037 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2038 \ ******************************\ |
2039 \ RC5_SampleEndOf: \ <---------------------+
2040 \ ******************************\
2041 BIC #$30,&RC5_TIM_CTL \ stop timer
2042 \ ******************************\
2043 \ RC5_ComputeNewRC5word \
2044 \ ******************************\
2045 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2046 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2047 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2048 \ ******************************\
2049 \ RC5_ComputeC6bit \
2050 \ ******************************\
2051 BIT #BIT14,T \ test /C6 bit in T
2052 0= IF BIS #BIT6,X \ set C6 bit in X
2053 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2054 \ ******************************\
2055 \ RC5_CommandByteIsDone \ -- BASE RC5_code
2056 \ ******************************\
2057 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
2058 \ ******************************\
2059 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2060 XOR @RSP,T \ (new XOR old) Toggle bits
2061 BIT #UF10,T \ repeated RC5_command ?
2062 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
2063 XOR #UF10,0(RSP) \ 5 toggle bit memory
2064 \ ******************************\
2065 \ Display IR_RC5 code \
2066 \ ******************************\
2067 SUB #8,PSP \ TOS -- x x x x TOS
2068 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
2069 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
2070 MOV #$10,&BASEADR \ set hexadecimal base
2071 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
2072 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
2073 LO2HI \ switch from assembler to FORTH
2074 LCD_CLEAR \ set LCD cursor at home
2075 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
2076 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2077 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
2078 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
2079 HI2LO \ -- switch from FORTH to assembler
2080 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
2081 MOV @PSP+,TOS \ -- TOS
2083 MOV @RSP+,SR \ restore SR flags
2084 BIC #%1111_1000,SR \ but force CPU Active Mode
2085 RET \ (instead of RETI)
2089 \ ------------------------------\
2090 HDNCODE STOP_R2L \ define new STOP_APP
2091 \ ------------------------------\
2092 CMP #RET_ADR,&{RC5TOLCD}+8 \
2093 0<> IF \ if previous START executing
2094 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
2095 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
2096 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
2097 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
2098 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
2099 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
2100 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
2101 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
2102 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
2103 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
2108 \ ------------------------------\
2110 \ ------------------------------\
2111 BW1 \ <-- INI_R2L for some events
2113 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
2115 ." RC5toLCD is removed,"
2116 ." type START to restart"
2119 \ ------------------------------\
2121 \ ------------------------------\
2122 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
2123 \ ------------------------------\
2125 \ ------------------------------\
2126 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
2127 \ ------------------------------\
2128 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
2129 \ ------------------------------\
2130 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
2131 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
2133 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
2134 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
2136 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
2137 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
2138 \ CMP #4,TOS \ hardware RST
2139 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
2140 \ CMP #2,TOS \ Power_ON event
2141 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2143 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
2145 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
2147 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
2148 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
2149 \ ------------------------------\
2150 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2151 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2152 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2153 \ -- \ID input divider \ 10 = /4
2154 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2155 \ - \TBCLR TimerB Clear
2158 \ -------------------------------\
2159 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2160 \ -- \CM Capture Mode
2165 \ --- \OUTMOD \ 011 = set/reset
2171 \ -------------------------------\
2173 \ -------------------------------\
2175 \ ------------------------------\
2176 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2177 \ ------------------------------\
2178 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2179 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2180 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
2181 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2183 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
2184 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2186 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2187 \ ------------------------------\
2188 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2189 \ ------------------------------\
2190 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2191 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2192 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2193 \ ------------------------------\
2194 BIS.B #LCDVo,&LCDVo_DIR \
2195 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2196 \ ------------------------------\
2197 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2198 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2199 \ ------------------------------\
2200 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2201 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2202 \ ******************************\
2204 \ ******************************\
2205 BIS.B #RC5,&IR_IE \ enable RC5_Int
2206 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2207 \ ******************************\
2208 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2209 \ ******************************\
2210 \ %01 0001 0100 \ TAxCTL
2211 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2212 \ -- \ ID divided by 1
2213 \ -- \ MC MODE = up to TAxCCRn
2214 \ - \ TACLR clear timer count
2217 \ ------------------------------\
2218 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2219 \ ------------------------------\
2221 \ --- \ TAIDEX pre divisor
2222 \ ------------------------------\
2223 \ %0000 0000 0000 0101 \ TAxCCR0
2224 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2225 \ ------------------------------\
2226 \ %0000 0000 0001 0000 \ TAxCCTL0
2227 \ - \ CAP capture/compare mode = compare
2230 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2231 \ ------------------------------\
2232 \ define LPM mode for ACCEPT \
2233 \ ------------------------------\
2234 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
2235 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2236 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2237 \ ------------------------------\
2239 \ ------------------------------\
2241 \ ------------------------------\
2242 #1000 20_US \ 1- wait 20 ms
2243 %011 TOP_LCD \ 2- send DB5=DB4=1
2244 #205 20_US \ 3- wait 4,1 ms
2245 %011 TOP_LCD \ 4- send again DB5=DB4=1
2246 #5 20_US \ 5- wait 0,1 ms
2247 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2248 #2 20_US \ wait 40 us = LCD cycle
2249 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2250 #2 20_US \ wait 40 us = LCD cycle
2251 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2252 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2253 LCD_CLEAR \ 10- "LCD_Clear"
2254 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2255 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2256 LCD_CLEAR \ 10- "LCD_Clear"
2257 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2258 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2259 CR ." I love you" \ display message on LCD
2260 ['] CR >BODY IS CR \ CR executes its default value
2261 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2262 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2265 \ ------------------------------\
2267 \ ------------------------------\
2268 CODE START \ this routine replaces WARM and COLD default values by these of this application.
2269 \ ------------------------------\
2270 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
2271 0= IF \ if not done, customizes MARKER_DOES
2272 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
2273 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
2274 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
2275 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
2276 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2277 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
2278 MOV #RC5_INT,&IR_VEC \ init interrupt vector
2279 MOV #INI_R2L,PC \ then execute new INI_APP, without return
2283 \ ------------------------------\
2286 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
2288 MARKER {RC5TOLCD} \ restore the state before MARKER definition
2289 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
2290 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
2291 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
2292 \ {RC5TOLCD}+14: make room to save previous IR_VEC
2294 [UNDEFINED] CONSTANT [IF]
2295 \ https://forth-standard.org/standard/core/CONSTANT
2296 \ CONSTANT <name> n -- define a Forth CONSTANT
2300 MOV TOS,-2(W) \ PFA = n
2307 [UNDEFINED] STATE [IF]
2308 \ https://forth-standard.org/standard/core/STATE
2309 \ STATE -- a-addr holds compiler state
2310 STATEADR CONSTANT STATE
2314 \ https://forth-standard.org/standard/core/Equal
2315 \ = x1 x2 -- flag test x1=x2
2322 XOR #-1,TOS \ 1 flag Z = 1
2327 [UNDEFINED] IF [IF] \ define IF and THEN
2328 \ https://forth-standard.org/standard/core/IF
2329 \ IF -- IFadr initialize conditional forward branch
2333 MOV &DP,TOS \ -- HERE
2334 ADD #4,&DP \ compile one word, reserve one word
2335 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
2336 ADD #2,TOS \ -- HERE+2=IFadr
2340 \ https://forth-standard.org/standard/core/THEN
2341 \ THEN IFadr -- resolve forward branch
2342 CODE THEN \ immediate
2343 MOV &DP,0(TOS) \ -- IFadr
2349 [UNDEFINED] ELSE [IF]
2350 \ https://forth-standard.org/standard/core/ELSE
2351 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
2352 CODE ELSE \ immediate
2353 ADD #4,&DP \ make room to compile two words
2354 MOV &DP,W \ W=HERE+4
2356 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
2358 MOV W,TOS \ -- ELSEadr
2363 [UNDEFINED] IS [IF] \ define DEFER! and IS
2365 \ https://forth-standard.org/standard/core/DEFERStore
2366 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2367 CODE DEFER! \ xt2 xt1 --
2368 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
2373 \ https://forth-standard.org/standard/core/IS
2376 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
2377 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
2378 \ or in a definition : ... ['] U. IS DISPLAY ...
2379 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2381 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2385 IF POSTPONE ['] POSTPONE DEFER!
2391 [UNDEFINED] >BODY [IF]
2392 \ https://forth-standard.org/standard/core/toBODY
2393 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2400 \ CODE 20uS \ n -- 8MHz version
2401 \ BEGIN \ 4 + 16 ~ loop
2402 \ MOV #39,rDOCON \ 39
2409 \ MOV #XDOCON,rDOCON \ 2
2414 CODE 20_US \ n -- n * 20 us
2415 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2417 BIT #1,&LCD_TIM_CTL \ 3
2418 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2419 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2421 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2426 CODE TOP_LCD \ LCD Sample
2427 \ \ if write : %xxxx_WWWW --
2428 \ \ if read : -- %0000_RRRR
2429 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2430 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2431 0= IF \ write LCD bits pattern
2433 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2434 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2437 THEN \ read LCD bits pattern
2440 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2441 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2446 CODE LCD_WRC \ char -- Write Char
2447 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2449 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
2450 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
2451 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2452 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2453 COLON \ high level word starts here
2454 TOP_LCD 2 20_US \ write high nibble first
2458 CODE LCD_WRF \ func -- Write Fonction
2459 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2463 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
2464 : LCD_HOME $02 LCD_WRF 100 20_us ;
2466 \ [UNDEFINED] OR [IF]
2468 \ \ https://forth-standard.org/standard/core/OR
2469 \ \ C OR x1 x2 -- x3 logical OR
2477 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
2478 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
2479 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
2480 \ : LCD_FN_SET $20 OR LCD_WrF ;
2481 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
2482 \ : LCD_GOTO $80 OR LCD_WrF ;
2485 \ CODE LCD_RDS \ -- status Read Status
2486 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2487 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2488 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2489 \ COLON \ starts a FORTH word
2490 \ TOP_LCD 2 20_us \ -- %0000_HHHH
2491 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
2492 \ HI2LO \ switch from FORTH to assembler
2493 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
2494 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
2495 \ MOV @RSP+,IP \ restore IP saved by COLON
2499 \ CODE LCD_RDC \ -- char Read Char
2500 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2505 \ ******************************\
2506 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2507 \ ******************************\
2508 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2509 BIT.B #SW2,&SW2_IN \ test switch S2
2510 0= IF \ case of switch S2 pressed
2511 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2513 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2516 BIT.B #SW1,&SW1_IN \ test switch S1 input
2517 0= IF \ case of Switch S1 pressed
2518 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2520 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2527 \ ******************************\
2528 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
2529 \ ******************************\
2530 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2531 \ ******************************\
2532 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2533 \ \ SMclock = 8|16|24 MHz
2534 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2535 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2536 \ \ SR(9)=new Toggle bit memory (ADD on)
2537 \ ******************************\
2538 \ RC5_FirstStartBitHalfCycle: \
2539 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2540 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
2541 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2543 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
2544 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2546 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
2547 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2549 MOV #1778,X \ RC5_Period * 1us
2550 MOV #14,W \ count of loop
2552 \ ******************************\
2553 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2554 \ ******************************\ |
2555 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2556 \ RC5_Compute_3/4_Period: \ |
2557 RRUM #1,X \ X=1/2 cycle |
2560 ADD X,Y \ Y=3/4 cycle
2561 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2563 \ ******************************\
2564 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2565 \ ******************************\
2566 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2567 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2568 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2569 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2570 SUB #1,W \ decrement count loop
2571 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2572 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2573 0<> WHILE \ ----> out of loop ----+
2574 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2576 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2577 CMP Y,X \ 1 | cycle time out of bound ?
2579 BIC #$30,&RC5_TIM_CTL \ | | stop timer
2580 GOTO FW1 \ | | quit on truncated RC5 message
2582 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2584 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2585 \ ******************************\ |
2586 \ RC5_SampleEndOf: \ <---------------------+
2587 \ ******************************\
2588 BIC #$30,&RC5_TIM_CTL \ stop timer
2589 \ ******************************\
2590 \ RC5_ComputeNewRC5word \
2591 \ ******************************\
2592 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2593 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2594 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2595 \ ******************************\
2596 \ RC5_ComputeC6bit \
2597 \ ******************************\
2598 BIT #BIT14,T \ test /C6 bit in T
2599 0= IF BIS #BIT6,X \ set C6 bit in X
2600 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2601 \ ******************************\
2602 \ RC5_CommandByteIsDone \ -- BASE RC5_code
2603 \ ******************************\
2604 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
2605 \ ******************************\
2606 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2607 XOR @RSP,T \ (new XOR old) Toggle bits
2608 BIT #UF10,T \ repeated RC5_command ?
2609 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
2610 XOR #UF10,0(RSP) \ 5 toggle bit memory
2611 \ ******************************\
2612 \ Display IR_RC5 code \
2613 \ ******************************\
2614 SUB #8,PSP \ TOS -- x x x x TOS
2615 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
2616 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
2617 MOV #$10,&BASEADR \ set hexadecimal base
2618 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
2619 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
2620 LO2HI \ switch from assembler to FORTH
2621 LCD_CLEAR \ set LCD cursor at home
2622 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
2623 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2624 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
2625 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
2626 HI2LO \ -- switch from FORTH to assembler
2627 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
2628 MOV @PSP+,TOS \ -- TOS
2630 MOV @RSP+,SR \ restore SR flags
2631 BIC #%1111_1000,SR \ but force CPU Active Mode
2632 RET \ (instead of RETI)
2636 \ ------------------------------\
2637 HDNCODE STOP_R2L \ define new STOP_APP
2638 \ ------------------------------\
2639 CMP #RET_ADR,&{RC5TOLCD}+8 \
2640 0<> IF \ if previous START executing
2641 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
2642 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
2643 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
2644 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
2645 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
2646 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
2647 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
2648 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
2649 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
2650 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
2655 \ ------------------------------\
2657 \ ------------------------------\
2658 BW1 \ <-- INI_R2L for some events
2660 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
2662 ." RC5toLCD is removed,"
2663 ." type START to restart"
2666 \ ------------------------------\
2668 \ ------------------------------\
2669 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
2670 \ ------------------------------\
2672 \ ------------------------------\
2673 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
2674 \ ------------------------------\
2675 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
2676 \ ------------------------------\
2677 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
2678 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
2680 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
2681 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
2683 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
2684 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
2685 \ CMP #4,TOS \ hardware RST
2686 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
2687 \ CMP #2,TOS \ Power_ON event
2688 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2690 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
2692 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
2694 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
2695 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
2696 \ ------------------------------\
2697 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2698 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2699 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2700 \ -- \ID input divider \ 10 = /4
2701 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2702 \ - \TBCLR TimerB Clear
2705 \ -------------------------------\
2706 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2707 \ -- \CM Capture Mode
2712 \ --- \OUTMOD \ 011 = set/reset
2718 \ -------------------------------\
2720 \ -------------------------------\
2722 \ ------------------------------\
2723 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2724 \ ------------------------------\
2725 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2726 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2727 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
2728 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2730 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
2731 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2733 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2734 \ ------------------------------\
2735 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2736 \ ------------------------------\
2737 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2738 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2739 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2740 \ ------------------------------\
2741 BIS.B #LCDVo,&LCDVo_DIR \
2742 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2743 \ ------------------------------\
2744 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2745 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2746 \ ------------------------------\
2747 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2748 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2749 \ ******************************\
2751 \ ******************************\
2752 BIS.B #RC5,&IR_IE \ enable RC5_Int
2753 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2754 \ ******************************\
2755 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2756 \ ******************************\
2757 \ %01 0001 0100 \ TAxCTL
2758 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2759 \ -- \ ID divided by 1
2760 \ -- \ MC MODE = up to TAxCCRn
2761 \ - \ TACLR clear timer count
2764 \ ------------------------------\
2765 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2766 \ ------------------------------\
2768 \ --- \ TAIDEX pre divisor
2769 \ ------------------------------\
2770 \ %0000 0000 0000 0101 \ TAxCCR0
2771 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2772 \ ------------------------------\
2773 \ %0000 0000 0001 0000 \ TAxCCTL0
2774 \ - \ CAP capture/compare mode = compare
2777 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2778 \ ------------------------------\
2779 \ define LPM mode for ACCEPT \
2780 \ ------------------------------\
2781 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
2782 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2783 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2784 \ ------------------------------\
2786 \ ------------------------------\
2788 \ ------------------------------\
2789 #1000 20_US \ 1- wait 20 ms
2790 %011 TOP_LCD \ 2- send DB5=DB4=1
2791 #205 20_US \ 3- wait 4,1 ms
2792 %011 TOP_LCD \ 4- send again DB5=DB4=1
2793 #5 20_US \ 5- wait 0,1 ms
2794 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2795 #2 20_US \ wait 40 us = LCD cycle
2796 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2797 #2 20_US \ wait 40 us = LCD cycle
2798 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2799 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2800 LCD_CLEAR \ 10- "LCD_Clear"
2801 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2802 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2803 LCD_CLEAR \ 10- "LCD_Clear"
2804 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2805 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2806 CR ." I love you" \ display message on LCD
2807 ['] CR >BODY IS CR \ CR executes its default value
2808 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2809 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2812 \ ------------------------------\
2814 \ ------------------------------\
2815 CODE START \ this routine replaces WARM and COLD default values by these of this application.
2816 \ ------------------------------\
2817 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
2818 0= IF \ if not done, customizes MARKER_DOES
2819 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
2820 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
2821 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
2822 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
2823 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2824 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
2825 MOV #RC5_INT,&IR_VEC \ init interrupt vector
2826 MOV #INI_R2L,PC \ then execute new INI_APP, without return
2830 \ ------------------------------\
2833 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
2835 MARKER {RC5TOLCD} \ restore the state before MARKER definition
2836 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
2837 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
2838 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
2839 \ {RC5TOLCD}+14: make room to save previous IR_VEC
2841 [UNDEFINED] CONSTANT [IF]
2842 \ https://forth-standard.org/standard/core/CONSTANT
2843 \ CONSTANT <name> n -- define a Forth CONSTANT
2847 MOV TOS,-2(W) \ PFA = n
2854 [UNDEFINED] STATE [IF]
2855 \ https://forth-standard.org/standard/core/STATE
2856 \ STATE -- a-addr holds compiler state
2857 STATEADR CONSTANT STATE
2861 \ https://forth-standard.org/standard/core/Equal
2862 \ = x1 x2 -- flag test x1=x2
2869 XOR #-1,TOS \ 1 flag Z = 1
2874 [UNDEFINED] IF [IF] \ define IF and THEN
2875 \ https://forth-standard.org/standard/core/IF
2876 \ IF -- IFadr initialize conditional forward branch
2880 MOV &DP,TOS \ -- HERE
2881 ADD #4,&DP \ compile one word, reserve one word
2882 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
2883 ADD #2,TOS \ -- HERE+2=IFadr
2887 \ https://forth-standard.org/standard/core/THEN
2888 \ THEN IFadr -- resolve forward branch
2889 CODE THEN \ immediate
2890 MOV &DP,0(TOS) \ -- IFadr
2896 [UNDEFINED] ELSE [IF]
2897 \ https://forth-standard.org/standard/core/ELSE
2898 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
2899 CODE ELSE \ immediate
2900 ADD #4,&DP \ make room to compile two words
2901 MOV &DP,W \ W=HERE+4
2903 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
2905 MOV W,TOS \ -- ELSEadr
2910 [UNDEFINED] IS [IF] \ define DEFER! and IS
2912 \ https://forth-standard.org/standard/core/DEFERStore
2913 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2914 CODE DEFER! \ xt2 xt1 --
2915 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
2920 \ https://forth-standard.org/standard/core/IS
2923 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
2924 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
2925 \ or in a definition : ... ['] U. IS DISPLAY ...
2926 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2928 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2932 IF POSTPONE ['] POSTPONE DEFER!
2938 [UNDEFINED] >BODY [IF]
2939 \ https://forth-standard.org/standard/core/toBODY
2940 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2947 \ CODE 20uS \ n -- 8MHz version
2948 \ BEGIN \ 4 + 16 ~ loop
2949 \ MOV #39,rDOCON \ 39
2956 \ MOV #XDOCON,rDOCON \ 2
2961 CODE 20_US \ n -- n * 20 us
2962 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2964 BIT #1,&LCD_TIM_CTL \ 3
2965 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2966 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2968 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2973 CODE TOP_LCD \ LCD Sample
2974 \ \ if write : %xxxx_WWWW --
2975 \ \ if read : -- %0000_RRRR
2976 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2977 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2978 0= IF \ write LCD bits pattern
2980 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2981 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2984 THEN \ read LCD bits pattern
2987 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2988 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2993 CODE LCD_WRC \ char -- Write Char
2994 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2996 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
2997 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
2998 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2999 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3000 COLON \ high level word starts here
3001 TOP_LCD 2 20_US \ write high nibble first
3005 CODE LCD_WRF \ func -- Write Fonction
3006 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3010 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3011 : LCD_HOME $02 LCD_WRF 100 20_us ;
3013 \ [UNDEFINED] OR [IF]
3015 \ \ https://forth-standard.org/standard/core/OR
3016 \ \ C OR x1 x2 -- x3 logical OR
3024 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
3025 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
3026 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
3027 \ : LCD_FN_SET $20 OR LCD_WrF ;
3028 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
3029 \ : LCD_GOTO $80 OR LCD_WrF ;
3032 \ CODE LCD_RDS \ -- status Read Status
3033 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3034 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3035 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3036 \ COLON \ starts a FORTH word
3037 \ TOP_LCD 2 20_us \ -- %0000_HHHH
3038 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
3039 \ HI2LO \ switch from FORTH to assembler
3040 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
3041 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
3042 \ MOV @RSP+,IP \ restore IP saved by COLON
3046 \ CODE LCD_RDC \ -- char Read Char
3047 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3052 \ ******************************\
3053 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3054 \ ******************************\
3055 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3056 BIT.B #SW2,&SW2_IN \ test switch S2
3057 0= IF \ case of switch S2 pressed
3058 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3060 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3063 BIT.B #SW1,&SW1_IN \ test switch S1 input
3064 0= IF \ case of Switch S1 pressed
3065 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3067 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3074 \ ******************************\
3075 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
3076 \ ******************************\
3077 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3078 \ ******************************\
3079 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3080 \ \ SMclock = 8|16|24 MHz
3081 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3082 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3083 \ \ SR(9)=new Toggle bit memory (ADD on)
3084 \ ******************************\
3085 \ RC5_FirstStartBitHalfCycle: \
3086 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3087 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
3088 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3090 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
3091 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3093 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
3094 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3096 MOV #1778,X \ RC5_Period * 1us
3097 MOV #14,W \ count of loop
3099 \ ******************************\
3100 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3101 \ ******************************\ |
3102 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3103 \ RC5_Compute_3/4_Period: \ |
3104 RRUM #1,X \ X=1/2 cycle |
3107 ADD X,Y \ Y=3/4 cycle
3108 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3110 \ ******************************\
3111 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3112 \ ******************************\
3113 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3114 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3115 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3116 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3117 SUB #1,W \ decrement count loop
3118 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3119 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3120 0<> WHILE \ ----> out of loop ----+
3121 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3123 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3124 CMP Y,X \ 1 | cycle time out of bound ?
3126 BIC #$30,&RC5_TIM_CTL \ | | stop timer
3127 GOTO FW1 \ | | quit on truncated RC5 message
3129 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3131 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3132 \ ******************************\ |
3133 \ RC5_SampleEndOf: \ <---------------------+
3134 \ ******************************\
3135 BIC #$30,&RC5_TIM_CTL \ stop timer
3136 \ ******************************\
3137 \ RC5_ComputeNewRC5word \
3138 \ ******************************\
3139 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3140 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3141 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3142 \ ******************************\
3143 \ RC5_ComputeC6bit \
3144 \ ******************************\
3145 BIT #BIT14,T \ test /C6 bit in T
3146 0= IF BIS #BIT6,X \ set C6 bit in X
3147 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3148 \ ******************************\
3149 \ RC5_CommandByteIsDone \ -- BASE RC5_code
3150 \ ******************************\
3151 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
3152 \ ******************************\
3153 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3154 XOR @RSP,T \ (new XOR old) Toggle bits
3155 BIT #UF10,T \ repeated RC5_command ?
3156 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
3157 XOR #UF10,0(RSP) \ 5 toggle bit memory
3158 \ ******************************\
3159 \ Display IR_RC5 code \
3160 \ ******************************\
3161 SUB #8,PSP \ TOS -- x x x x TOS
3162 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
3163 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
3164 MOV #$10,&BASEADR \ set hexadecimal base
3165 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
3166 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
3167 LO2HI \ switch from assembler to FORTH
3168 LCD_CLEAR \ set LCD cursor at home
3169 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
3170 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3171 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
3172 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
3173 HI2LO \ -- switch from FORTH to assembler
3174 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
3175 MOV @PSP+,TOS \ -- TOS
3177 MOV @RSP+,SR \ restore SR flags
3178 BIC #%1111_1000,SR \ but force CPU Active Mode
3179 RET \ (instead of RETI)
3183 \ ------------------------------\
3184 HDNCODE STOP_R2L \ define new STOP_APP
3185 \ ------------------------------\
3186 CMP #RET_ADR,&{RC5TOLCD}+8 \
3187 0<> IF \ if previous START executing
3188 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
3189 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
3190 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
3191 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
3192 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
3193 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
3194 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
3195 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
3196 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
3197 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
3202 \ ------------------------------\
3204 \ ------------------------------\
3205 BW1 \ <-- INI_R2L for some events
3207 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
3209 ." RC5toLCD is removed,"
3210 ." type START to restart"
3213 \ ------------------------------\
3215 \ ------------------------------\
3216 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
3217 \ ------------------------------\
3219 \ ------------------------------\
3220 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
3221 \ ------------------------------\
3222 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
3223 \ ------------------------------\
3224 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
3225 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
3227 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
3228 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
3230 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
3231 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
3232 \ CMP #4,TOS \ hardware RST
3233 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
3234 \ CMP #2,TOS \ Power_ON event
3235 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3237 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
3239 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
3241 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
3242 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
3243 \ ------------------------------\
3244 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3245 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3246 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3247 \ -- \ID input divider \ 10 = /4
3248 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3249 \ - \TBCLR TimerB Clear
3252 \ -------------------------------\
3253 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3254 \ -- \CM Capture Mode
3259 \ --- \OUTMOD \ 011 = set/reset
3265 \ -------------------------------\
3267 \ -------------------------------\
3269 \ ------------------------------\
3270 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3271 \ ------------------------------\
3272 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3273 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3274 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
3275 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3277 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
3278 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3280 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3281 \ ------------------------------\
3282 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3283 \ ------------------------------\
3284 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3285 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3286 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3287 \ ------------------------------\
3288 BIS.B #LCDVo,&LCDVo_DIR \
3289 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3290 \ ------------------------------\
3291 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3292 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3293 \ ------------------------------\
3294 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3295 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3296 \ ******************************\
3298 \ ******************************\
3299 BIS.B #RC5,&IR_IE \ enable RC5_Int
3300 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3301 \ ******************************\
3302 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3303 \ ******************************\
3304 \ %01 0001 0100 \ TAxCTL
3305 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3306 \ -- \ ID divided by 1
3307 \ -- \ MC MODE = up to TAxCCRn
3308 \ - \ TACLR clear timer count
3311 \ ------------------------------\
3312 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3313 \ ------------------------------\
3315 \ --- \ TAIDEX pre divisor
3316 \ ------------------------------\
3317 \ %0000 0000 0000 0101 \ TAxCCR0
3318 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3319 \ ------------------------------\
3320 \ %0000 0000 0001 0000 \ TAxCCTL0
3321 \ - \ CAP capture/compare mode = compare
3324 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3325 \ ------------------------------\
3326 \ define LPM mode for ACCEPT \
3327 \ ------------------------------\
3328 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
3329 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3330 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3331 \ ------------------------------\
3333 \ ------------------------------\
3335 \ ------------------------------\
3336 #1000 20_US \ 1- wait 20 ms
3337 %011 TOP_LCD \ 2- send DB5=DB4=1
3338 #205 20_US \ 3- wait 4,1 ms
3339 %011 TOP_LCD \ 4- send again DB5=DB4=1
3340 #5 20_US \ 5- wait 0,1 ms
3341 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3342 #2 20_US \ wait 40 us = LCD cycle
3343 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3344 #2 20_US \ wait 40 us = LCD cycle
3345 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3346 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3347 LCD_CLEAR \ 10- "LCD_Clear"
3348 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3349 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3350 LCD_CLEAR \ 10- "LCD_Clear"
3351 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3352 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3353 CR ." I love you" \ display message on LCD
3354 ['] CR >BODY IS CR \ CR executes its default value
3355 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3356 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3359 \ ------------------------------\
3361 \ ------------------------------\
3362 CODE START \ this routine replaces WARM and COLD default values by these of this application.
3363 \ ------------------------------\
3364 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
3365 0= IF \ if not done, customizes MARKER_DOES
3366 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
3367 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
3368 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
3369 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
3370 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3371 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
3372 MOV #RC5_INT,&IR_VEC \ init interrupt vector
3373 MOV #INI_R2L,PC \ then execute new INI_APP, without return
3377 \ ------------------------------\
3380 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
3382 MARKER {RC5TOLCD} \ restore the state before MARKER definition
3383 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
3384 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
3385 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
3386 \ {RC5TOLCD}+14: make room to save previous IR_VEC
3388 [UNDEFINED] CONSTANT [IF]
3389 \ https://forth-standard.org/standard/core/CONSTANT
3390 \ CONSTANT <name> n -- define a Forth CONSTANT
3394 MOV TOS,-2(W) \ PFA = n
3401 [UNDEFINED] STATE [IF]
3402 \ https://forth-standard.org/standard/core/STATE
3403 \ STATE -- a-addr holds compiler state
3404 STATEADR CONSTANT STATE
3408 \ https://forth-standard.org/standard/core/Equal
3409 \ = x1 x2 -- flag test x1=x2
3416 XOR #-1,TOS \ 1 flag Z = 1
3421 [UNDEFINED] IF [IF] \ define IF and THEN
3422 \ https://forth-standard.org/standard/core/IF
3423 \ IF -- IFadr initialize conditional forward branch
3427 MOV &DP,TOS \ -- HERE
3428 ADD #4,&DP \ compile one word, reserve one word
3429 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
3430 ADD #2,TOS \ -- HERE+2=IFadr
3434 \ https://forth-standard.org/standard/core/THEN
3435 \ THEN IFadr -- resolve forward branch
3436 CODE THEN \ immediate
3437 MOV &DP,0(TOS) \ -- IFadr
3443 [UNDEFINED] ELSE [IF]
3444 \ https://forth-standard.org/standard/core/ELSE
3445 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
3446 CODE ELSE \ immediate
3447 ADD #4,&DP \ make room to compile two words
3448 MOV &DP,W \ W=HERE+4
3450 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
3452 MOV W,TOS \ -- ELSEadr
3457 [UNDEFINED] IS [IF] \ define DEFER! and IS
3459 \ https://forth-standard.org/standard/core/DEFERStore
3460 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3461 CODE DEFER! \ xt2 xt1 --
3462 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
3467 \ https://forth-standard.org/standard/core/IS
3470 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
3471 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
3472 \ or in a definition : ... ['] U. IS DISPLAY ...
3473 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3475 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3479 IF POSTPONE ['] POSTPONE DEFER!
3485 [UNDEFINED] >BODY [IF]
3486 \ https://forth-standard.org/standard/core/toBODY
3487 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3494 \ CODE 20uS \ n -- 8MHz version
3495 \ BEGIN \ 4 + 16 ~ loop
3496 \ MOV #39,rDOCON \ 39
3503 \ MOV #XDOCON,rDOCON \ 2
3508 CODE 20_US \ n -- n * 20 us
3509 BEGIN \ here we presume that LCD_TIM_IFG = 1...
3511 BIT #1,&LCD_TIM_CTL \ 3
3512 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
3513 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
3515 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
3520 CODE TOP_LCD \ LCD Sample
3521 \ \ if write : %xxxx_WWWW --
3522 \ \ if read : -- %0000_RRRR
3523 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3524 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3525 0= IF \ write LCD bits pattern
3527 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3528 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3531 THEN \ read LCD bits pattern
3534 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3535 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3540 CODE LCD_WRC \ char -- Write Char
3541 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3543 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
3544 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
3545 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3546 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3547 COLON \ high level word starts here
3548 TOP_LCD 2 20_US \ write high nibble first
3552 CODE LCD_WRF \ func -- Write Fonction
3553 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3557 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3558 : LCD_HOME $02 LCD_WRF 100 20_us ;
3560 \ [UNDEFINED] OR [IF]
3562 \ \ https://forth-standard.org/standard/core/OR
3563 \ \ C OR x1 x2 -- x3 logical OR
3571 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
3572 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
3573 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
3574 \ : LCD_FN_SET $20 OR LCD_WrF ;
3575 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
3576 \ : LCD_GOTO $80 OR LCD_WrF ;
3579 \ CODE LCD_RDS \ -- status Read Status
3580 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3581 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3582 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3583 \ COLON \ starts a FORTH word
3584 \ TOP_LCD 2 20_us \ -- %0000_HHHH
3585 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
3586 \ HI2LO \ switch from FORTH to assembler
3587 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
3588 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
3589 \ MOV @RSP+,IP \ restore IP saved by COLON
3593 \ CODE LCD_RDC \ -- char Read Char
3594 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3599 \ ******************************\
3600 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3601 \ ******************************\
3602 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3603 BIT.B #SW2,&SW2_IN \ test switch S2
3604 0= IF \ case of switch S2 pressed
3605 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3607 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3610 BIT.B #SW1,&SW1_IN \ test switch S1 input
3611 0= IF \ case of Switch S1 pressed
3612 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3614 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3621 \ ******************************\
3622 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
3623 \ ******************************\
3624 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3625 \ ******************************\
3626 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3627 \ \ SMclock = 8|16|24 MHz
3628 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3629 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3630 \ \ SR(9)=new Toggle bit memory (ADD on)
3631 \ ******************************\
3632 \ RC5_FirstStartBitHalfCycle: \
3633 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3634 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
3635 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3637 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
3638 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3640 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
3641 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3643 MOV #1778,X \ RC5_Period * 1us
3644 MOV #14,W \ count of loop
3646 \ ******************************\
3647 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3648 \ ******************************\ |
3649 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3650 \ RC5_Compute_3/4_Period: \ |
3651 RRUM #1,X \ X=1/2 cycle |
3654 ADD X,Y \ Y=3/4 cycle
3655 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3657 \ ******************************\
3658 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3659 \ ******************************\
3660 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3661 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3662 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3663 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3664 SUB #1,W \ decrement count loop
3665 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3666 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3667 0<> WHILE \ ----> out of loop ----+
3668 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3670 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3671 CMP Y,X \ 1 | cycle time out of bound ?
3673 BIC #$30,&RC5_TIM_CTL \ | | stop timer
3674 GOTO FW1 \ | | quit on truncated RC5 message
3676 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3678 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3679 \ ******************************\ |
3680 \ RC5_SampleEndOf: \ <---------------------+
3681 \ ******************************\
3682 BIC #$30,&RC5_TIM_CTL \ stop timer
3683 \ ******************************\
3684 \ RC5_ComputeNewRC5word \
3685 \ ******************************\
3686 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3687 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3688 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3689 \ ******************************\
3690 \ RC5_ComputeC6bit \
3691 \ ******************************\
3692 BIT #BIT14,T \ test /C6 bit in T
3693 0= IF BIS #BIT6,X \ set C6 bit in X
3694 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3695 \ ******************************\
3696 \ RC5_CommandByteIsDone \ -- BASE RC5_code
3697 \ ******************************\
3698 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
3699 \ ******************************\
3700 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3701 XOR @RSP,T \ (new XOR old) Toggle bits
3702 BIT #UF10,T \ repeated RC5_command ?
3703 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
3704 XOR #UF10,0(RSP) \ 5 toggle bit memory
3705 \ ******************************\
3706 \ Display IR_RC5 code \
3707 \ ******************************\
3708 SUB #8,PSP \ TOS -- x x x x TOS
3709 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
3710 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
3711 MOV #$10,&BASEADR \ set hexadecimal base
3712 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
3713 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
3714 LO2HI \ switch from assembler to FORTH
3715 LCD_CLEAR \ set LCD cursor at home
3716 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
3717 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3718 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
3719 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
3720 HI2LO \ -- switch from FORTH to assembler
3721 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
3722 MOV @PSP+,TOS \ -- TOS
3724 MOV @RSP+,SR \ restore SR flags
3725 BIC #%1111_1000,SR \ but force CPU Active Mode
3726 RET \ (instead of RETI)
3730 \ ------------------------------\
3731 HDNCODE STOP_R2L \ define new STOP_APP
3732 \ ------------------------------\
3733 CMP #RET_ADR,&{RC5TOLCD}+8 \
3734 0<> IF \ if previous START executing
3735 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
3736 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
3737 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
3738 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
3739 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
3740 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
3741 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
3742 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
3743 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
3744 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
3749 \ ------------------------------\
3751 \ ------------------------------\
3752 BW1 \ <-- INI_R2L for some events
3754 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
3756 ." RC5toLCD is removed,"
3757 ." type START to restart"
3760 \ ------------------------------\
3762 \ ------------------------------\
3763 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
3764 \ ------------------------------\
3766 \ ------------------------------\
3767 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
3768 \ ------------------------------\
3769 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
3770 \ ------------------------------\
3771 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
3772 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
3774 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
3775 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
3777 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
3778 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
3779 \ CMP #4,TOS \ hardware RST
3780 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
3781 \ CMP #2,TOS \ Power_ON event
3782 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3784 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
3786 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
3788 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
3789 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
3790 \ ------------------------------\
3791 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3792 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3793 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3794 \ -- \ID input divider \ 10 = /4
3795 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3796 \ - \TBCLR TimerB Clear
3799 \ -------------------------------\
3800 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3801 \ -- \CM Capture Mode
3806 \ --- \OUTMOD \ 011 = set/reset
3812 \ -------------------------------\
3814 \ -------------------------------\
3816 \ ------------------------------\
3817 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3818 \ ------------------------------\
3819 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3820 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3821 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
3822 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3824 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
3825 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3827 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3828 \ ------------------------------\
3829 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3830 \ ------------------------------\
3831 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3832 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3833 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3834 \ ------------------------------\
3835 BIS.B #LCDVo,&LCDVo_DIR \
3836 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3837 \ ------------------------------\
3838 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3839 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3840 \ ------------------------------\
3841 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3842 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3843 \ ******************************\
3845 \ ******************************\
3846 BIS.B #RC5,&IR_IE \ enable RC5_Int
3847 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3848 \ ******************************\
3849 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3850 \ ******************************\
3851 \ %01 0001 0100 \ TAxCTL
3852 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3853 \ -- \ ID divided by 1
3854 \ -- \ MC MODE = up to TAxCCRn
3855 \ - \ TACLR clear timer count
3858 \ ------------------------------\
3859 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3860 \ ------------------------------\
3862 \ --- \ TAIDEX pre divisor
3863 \ ------------------------------\
3864 \ %0000 0000 0000 0101 \ TAxCCR0
3865 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3866 \ ------------------------------\
3867 \ %0000 0000 0001 0000 \ TAxCCTL0
3868 \ - \ CAP capture/compare mode = compare
3871 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3872 \ ------------------------------\
3873 \ define LPM mode for ACCEPT \
3874 \ ------------------------------\
3875 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
3876 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3877 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3878 \ ------------------------------\
3880 \ ------------------------------\
3882 \ ------------------------------\
3883 #1000 20_US \ 1- wait 20 ms
3884 %011 TOP_LCD \ 2- send DB5=DB4=1
3885 #205 20_US \ 3- wait 4,1 ms
3886 %011 TOP_LCD \ 4- send again DB5=DB4=1
3887 #5 20_US \ 5- wait 0,1 ms
3888 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3889 #2 20_US \ wait 40 us = LCD cycle
3890 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3891 #2 20_US \ wait 40 us = LCD cycle
3892 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3893 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3894 LCD_CLEAR \ 10- "LCD_Clear"
3895 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3896 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3897 LCD_CLEAR \ 10- "LCD_Clear"
3898 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3899 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3900 CR ." I love you" \ display message on LCD
3901 ['] CR >BODY IS CR \ CR executes its default value
3902 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3903 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3906 \ ------------------------------\
3908 \ ------------------------------\
3909 CODE START \ this routine replaces WARM and COLD default values by these of this application.
3910 \ ------------------------------\
3911 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
3912 0= IF \ if not done, customizes MARKER_DOES
3913 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
3914 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
3915 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
3916 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
3917 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3918 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
3919 MOV #RC5_INT,&IR_VEC \ init interrupt vector
3920 MOV #INI_R2L,PC \ then execute new INI_APP, without return
3924 \ ------------------------------\
3927 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
3929 MARKER {RC5TOLCD} \ restore the state before MARKER definition
3930 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
3931 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
3932 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
3933 \ {RC5TOLCD}+14: make room to save previous IR_VEC
3935 [UNDEFINED] CONSTANT [IF]
3936 \ https://forth-standard.org/standard/core/CONSTANT
3937 \ CONSTANT <name> n -- define a Forth CONSTANT
3941 MOV TOS,-2(W) \ PFA = n
3948 [UNDEFINED] STATE [IF]
3949 \ https://forth-standard.org/standard/core/STATE
3950 \ STATE -- a-addr holds compiler state
3951 STATEADR CONSTANT STATE
3955 \ https://forth-standard.org/standard/core/Equal
3956 \ = x1 x2 -- flag test x1=x2
3963 XOR #-1,TOS \ 1 flag Z = 1
3968 [UNDEFINED] IF [IF] \ define IF and THEN
3969 \ https://forth-standard.org/standard/core/IF
3970 \ IF -- IFadr initialize conditional forward branch
3974 MOV &DP,TOS \ -- HERE
3975 ADD #4,&DP \ compile one word, reserve one word
3976 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
3977 ADD #2,TOS \ -- HERE+2=IFadr
3981 \ https://forth-standard.org/standard/core/THEN
3982 \ THEN IFadr -- resolve forward branch
3983 CODE THEN \ immediate
3984 MOV &DP,0(TOS) \ -- IFadr
3990 [UNDEFINED] ELSE [IF]
3991 \ https://forth-standard.org/standard/core/ELSE
3992 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
3993 CODE ELSE \ immediate
3994 ADD #4,&DP \ make room to compile two words
3995 MOV &DP,W \ W=HERE+4
3997 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
3999 MOV W,TOS \ -- ELSEadr
4004 [UNDEFINED] IS [IF] \ define DEFER! and IS
4006 \ https://forth-standard.org/standard/core/DEFERStore
4007 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
4008 CODE DEFER! \ xt2 xt1 --
4009 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
4014 \ https://forth-standard.org/standard/core/IS
4017 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
4018 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
4019 \ or in a definition : ... ['] U. IS DISPLAY ...
4020 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
4022 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
4026 IF POSTPONE ['] POSTPONE DEFER!
4032 [UNDEFINED] >BODY [IF]
4033 \ https://forth-standard.org/standard/core/toBODY
4034 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
4041 \ CODE 20uS \ n -- 8MHz version
4042 \ BEGIN \ 4 + 16 ~ loop
4043 \ MOV #39,rDOCON \ 39
4050 \ MOV #XDOCON,rDOCON \ 2
4055 CODE 20_US \ n -- n * 20 us
4056 BEGIN \ here we presume that LCD_TIM_IFG = 1...
4058 BIT #1,&LCD_TIM_CTL \ 3
4059 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
4060 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
4062 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4067 CODE TOP_LCD \ LCD Sample
4068 \ \ if write : %xxxx_WWWW --
4069 \ \ if read : -- %0000_RRRR
4070 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4071 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4072 0= IF \ write LCD bits pattern
4074 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4075 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4078 THEN \ read LCD bits pattern
4081 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4082 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4087 CODE LCD_WRC \ char -- Write Char
4088 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4090 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
4091 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
4092 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4093 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4094 COLON \ high level word starts here
4095 TOP_LCD 2 20_US \ write high nibble first
4099 CODE LCD_WRF \ func -- Write Fonction
4100 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4104 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4105 : LCD_HOME $02 LCD_WRF 100 20_us ;
4107 \ [UNDEFINED] OR [IF]
4109 \ \ https://forth-standard.org/standard/core/OR
4110 \ \ C OR x1 x2 -- x3 logical OR
4118 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
4119 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
4120 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
4121 \ : LCD_FN_SET $20 OR LCD_WrF ;
4122 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
4123 \ : LCD_GOTO $80 OR LCD_WrF ;
4126 \ CODE LCD_RDS \ -- status Read Status
4127 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4128 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4129 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4130 \ COLON \ starts a FORTH word
4131 \ TOP_LCD 2 20_us \ -- %0000_HHHH
4132 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
4133 \ HI2LO \ switch from FORTH to assembler
4134 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
4135 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
4136 \ MOV @RSP+,IP \ restore IP saved by COLON
4140 \ CODE LCD_RDC \ -- char Read Char
4141 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4146 \ ******************************\
4147 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4148 \ ******************************\
4149 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4150 BIT.B #SW2,&SW2_IN \ test switch S2
4151 0= IF \ case of switch S2 pressed
4152 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4154 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4157 BIT.B #SW1,&SW1_IN \ test switch S1 input
4158 0= IF \ case of Switch S1 pressed
4159 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4161 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4168 \ ******************************\
4169 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
4170 \ ******************************\
4171 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4172 \ ******************************\
4173 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4174 \ \ SMclock = 8|16|24 MHz
4175 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4176 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4177 \ \ SR(9)=new Toggle bit memory (ADD on)
4178 \ ******************************\
4179 \ RC5_FirstStartBitHalfCycle: \
4180 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4181 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
4182 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4184 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
4185 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4187 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
4188 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4190 MOV #1778,X \ RC5_Period * 1us
4191 MOV #14,W \ count of loop
4193 \ ******************************\
4194 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4195 \ ******************************\ |
4196 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4197 \ RC5_Compute_3/4_Period: \ |
4198 RRUM #1,X \ X=1/2 cycle |
4201 ADD X,Y \ Y=3/4 cycle
4202 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4204 \ ******************************\
4205 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4206 \ ******************************\
4207 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4208 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4209 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4210 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4211 SUB #1,W \ decrement count loop
4212 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4213 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4214 0<> WHILE \ ----> out of loop ----+
4215 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4217 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4218 CMP Y,X \ 1 | cycle time out of bound ?
4220 BIC #$30,&RC5_TIM_CTL \ | | stop timer
4221 GOTO FW1 \ | | quit on truncated RC5 message
4223 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4225 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4226 \ ******************************\ |
4227 \ RC5_SampleEndOf: \ <---------------------+
4228 \ ******************************\
4229 BIC #$30,&RC5_TIM_CTL \ stop timer
4230 \ ******************************\
4231 \ RC5_ComputeNewRC5word \
4232 \ ******************************\
4233 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4234 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4235 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4236 \ ******************************\
4237 \ RC5_ComputeC6bit \
4238 \ ******************************\
4239 BIT #BIT14,T \ test /C6 bit in T
4240 0= IF BIS #BIT6,X \ set C6 bit in X
4241 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4242 \ ******************************\
4243 \ RC5_CommandByteIsDone \ -- BASE RC5_code
4244 \ ******************************\
4245 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
4246 \ ******************************\
4247 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4248 XOR @RSP,T \ (new XOR old) Toggle bits
4249 BIT #UF10,T \ repeated RC5_command ?
4250 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
4251 XOR #UF10,0(RSP) \ 5 toggle bit memory
4252 \ ******************************\
4253 \ Display IR_RC5 code \
4254 \ ******************************\
4255 SUB #8,PSP \ TOS -- x x x x TOS
4256 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
4257 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
4258 MOV #$10,&BASEADR \ set hexadecimal base
4259 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
4260 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
4261 LO2HI \ switch from assembler to FORTH
4262 LCD_CLEAR \ set LCD cursor at home
4263 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
4264 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4265 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
4266 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
4267 HI2LO \ -- switch from FORTH to assembler
4268 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
4269 MOV @PSP+,TOS \ -- TOS
4271 MOV @RSP+,SR \ restore SR flags
4272 BIC #%1111_1000,SR \ but force CPU Active Mode
4273 RET \ (instead of RETI)
4277 \ ------------------------------\
4278 HDNCODE STOP_R2L \ define new STOP_APP
4279 \ ------------------------------\
4280 CMP #RET_ADR,&{RC5TOLCD}+8 \
4281 0<> IF \ if previous START executing
4282 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
4283 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
4284 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
4285 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
4286 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
4287 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
4288 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
4289 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
4290 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
4291 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
4296 \ ------------------------------\
4298 \ ------------------------------\
4299 BW1 \ <-- INI_R2L for some events
4301 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4303 ." RC5toLCD is removed,"
4304 ." type START to restart"
4307 \ ------------------------------\
4309 \ ------------------------------\
4310 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
4311 \ ------------------------------\
4313 \ ------------------------------\
4314 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
4315 \ ------------------------------\
4316 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
4317 \ ------------------------------\
4318 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
4319 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
4321 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
4322 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
4324 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
4325 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
4326 \ CMP #4,TOS \ hardware RST
4327 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
4328 \ CMP #2,TOS \ Power_ON event
4329 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4331 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4333 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4335 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4336 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
4337 \ ------------------------------\
4338 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4339 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4340 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4341 \ -- \ID input divider \ 10 = /4
4342 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4343 \ - \TBCLR TimerB Clear
4346 \ -------------------------------\
4347 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4348 \ -- \CM Capture Mode
4353 \ --- \OUTMOD \ 011 = set/reset
4359 \ -------------------------------\
4361 \ -------------------------------\
4363 \ ------------------------------\
4364 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4365 \ ------------------------------\
4366 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4367 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4368 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4369 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4371 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4372 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4374 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4375 \ ------------------------------\
4376 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4377 \ ------------------------------\
4378 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4379 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4380 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4381 \ ------------------------------\
4382 BIS.B #LCDVo,&LCDVo_DIR \
4383 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4384 \ ------------------------------\
4385 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4386 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4387 \ ------------------------------\
4388 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4389 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4390 \ ******************************\
4392 \ ******************************\
4393 BIS.B #RC5,&IR_IE \ enable RC5_Int
4394 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4395 \ ******************************\
4396 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4397 \ ******************************\
4398 \ %01 0001 0100 \ TAxCTL
4399 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4400 \ -- \ ID divided by 1
4401 \ -- \ MC MODE = up to TAxCCRn
4402 \ - \ TACLR clear timer count
4405 \ ------------------------------\
4406 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4407 \ ------------------------------\
4409 \ --- \ TAIDEX pre divisor
4410 \ ------------------------------\
4411 \ %0000 0000 0000 0101 \ TAxCCR0
4412 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4413 \ ------------------------------\
4414 \ %0000 0000 0001 0000 \ TAxCCTL0
4415 \ - \ CAP capture/compare mode = compare
4418 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4419 \ ------------------------------\
4420 \ define LPM mode for ACCEPT \
4421 \ ------------------------------\
4422 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
4423 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4424 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4425 \ ------------------------------\
4427 \ ------------------------------\
4429 \ ------------------------------\
4430 #1000 20_US \ 1- wait 20 ms
4431 %011 TOP_LCD \ 2- send DB5=DB4=1
4432 #205 20_US \ 3- wait 4,1 ms
4433 %011 TOP_LCD \ 4- send again DB5=DB4=1
4434 #5 20_US \ 5- wait 0,1 ms
4435 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4436 #2 20_US \ wait 40 us = LCD cycle
4437 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4438 #2 20_US \ wait 40 us = LCD cycle
4439 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4440 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4441 LCD_CLEAR \ 10- "LCD_Clear"
4442 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4443 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4444 LCD_CLEAR \ 10- "LCD_Clear"
4445 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4446 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4447 CR ." I love you" \ display message on LCD
4448 ['] CR >BODY IS CR \ CR executes its default value
4449 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4450 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
4453 \ ------------------------------\
4455 \ ------------------------------\
4456 CODE START \ this routine replaces WARM and COLD default values by these of this application.
4457 \ ------------------------------\
4458 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
4459 0= IF \ if not done, customizes MARKER_DOES
4460 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
4461 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
4462 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
4463 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
4464 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4465 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
4466 MOV #RC5_INT,&IR_VEC \ init interrupt vector
4467 MOV #INI_R2L,PC \ then execute new INI_APP, without return
4471 \ ------------------------------\
4474 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
4476 MARKER {RC5TOLCD} \ restore the state before MARKER definition
4477 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
4478 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
4479 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
4480 \ {RC5TOLCD}+14: make room to save previous IR_VEC
4482 [UNDEFINED] CONSTANT [IF]
4483 \ https://forth-standard.org/standard/core/CONSTANT
4484 \ CONSTANT <name> n -- define a Forth CONSTANT
4488 MOV TOS,-2(W) \ PFA = n
4495 [UNDEFINED] STATE [IF]
4496 \ https://forth-standard.org/standard/core/STATE
4497 \ STATE -- a-addr holds compiler state
4498 STATEADR CONSTANT STATE
4502 \ https://forth-standard.org/standard/core/Equal
4503 \ = x1 x2 -- flag test x1=x2
4510 XOR #-1,TOS \ 1 flag Z = 1
4515 [UNDEFINED] IF [IF] \ define IF and THEN
4516 \ https://forth-standard.org/standard/core/IF
4517 \ IF -- IFadr initialize conditional forward branch
4521 MOV &DP,TOS \ -- HERE
4522 ADD #4,&DP \ compile one word, reserve one word
4523 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
4524 ADD #2,TOS \ -- HERE+2=IFadr
4528 \ https://forth-standard.org/standard/core/THEN
4529 \ THEN IFadr -- resolve forward branch
4530 CODE THEN \ immediate
4531 MOV &DP,0(TOS) \ -- IFadr
4537 [UNDEFINED] ELSE [IF]
4538 \ https://forth-standard.org/standard/core/ELSE
4539 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
4540 CODE ELSE \ immediate
4541 ADD #4,&DP \ make room to compile two words
4542 MOV &DP,W \ W=HERE+4
4544 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
4546 MOV W,TOS \ -- ELSEadr
4551 [UNDEFINED] IS [IF] \ define DEFER! and IS
4553 \ https://forth-standard.org/standard/core/DEFERStore
4554 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
4555 CODE DEFER! \ xt2 xt1 --
4556 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
4561 \ https://forth-standard.org/standard/core/IS
4564 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
4565 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
4566 \ or in a definition : ... ['] U. IS DISPLAY ...
4567 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
4569 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
4573 IF POSTPONE ['] POSTPONE DEFER!
4579 [UNDEFINED] >BODY [IF]
4580 \ https://forth-standard.org/standard/core/toBODY
4581 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
4588 \ CODE 20uS \ n -- 8MHz version
4589 \ BEGIN \ 4 + 16 ~ loop
4590 \ MOV #39,rDOCON \ 39
4597 \ MOV #XDOCON,rDOCON \ 2
4602 CODE 20_US \ n -- n * 20 us
4603 BEGIN \ here we presume that LCD_TIM_IFG = 1...
4605 BIT #1,&LCD_TIM_CTL \ 3
4606 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
4607 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
4609 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4614 CODE TOP_LCD \ LCD Sample
4615 \ \ if write : %xxxx_WWWW --
4616 \ \ if read : -- %0000_RRRR
4617 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4618 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4619 0= IF \ write LCD bits pattern
4621 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4622 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4625 THEN \ read LCD bits pattern
4628 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4629 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4634 CODE LCD_WRC \ char -- Write Char
4635 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4637 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
4638 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
4639 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4640 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4641 COLON \ high level word starts here
4642 TOP_LCD 2 20_US \ write high nibble first
4646 CODE LCD_WRF \ func -- Write Fonction
4647 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4651 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4652 : LCD_HOME $02 LCD_WRF 100 20_us ;
4654 \ [UNDEFINED] OR [IF]
4656 \ \ https://forth-standard.org/standard/core/OR
4657 \ \ C OR x1 x2 -- x3 logical OR
4665 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
4666 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
4667 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
4668 \ : LCD_FN_SET $20 OR LCD_WrF ;
4669 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
4670 \ : LCD_GOTO $80 OR LCD_WrF ;
4673 \ CODE LCD_RDS \ -- status Read Status
4674 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4675 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4676 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4677 \ COLON \ starts a FORTH word
4678 \ TOP_LCD 2 20_us \ -- %0000_HHHH
4679 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
4680 \ HI2LO \ switch from FORTH to assembler
4681 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
4682 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
4683 \ MOV @RSP+,IP \ restore IP saved by COLON
4687 \ CODE LCD_RDC \ -- char Read Char
4688 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4693 \ ******************************\
4694 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4695 \ ******************************\
4696 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4697 BIT.B #SW2,&SW2_IN \ test switch S2
4698 0= IF \ case of switch S2 pressed
4699 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4701 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4704 BIT.B #SW1,&SW1_IN \ test switch S1 input
4705 0= IF \ case of Switch S1 pressed
4706 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4708 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4715 \ ******************************\
4716 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
4717 \ ******************************\
4718 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4719 \ ******************************\
4720 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4721 \ \ SMclock = 8|16|24 MHz
4722 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4723 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4724 \ \ SR(9)=new Toggle bit memory (ADD on)
4725 \ ******************************\
4726 \ RC5_FirstStartBitHalfCycle: \
4727 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4728 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
4729 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4731 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
4732 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4734 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
4735 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4737 MOV #1778,X \ RC5_Period * 1us
4738 MOV #14,W \ count of loop
4740 \ ******************************\
4741 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4742 \ ******************************\ |
4743 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4744 \ RC5_Compute_3/4_Period: \ |
4745 RRUM #1,X \ X=1/2 cycle |
4748 ADD X,Y \ Y=3/4 cycle
4749 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4751 \ ******************************\
4752 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4753 \ ******************************\
4754 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4755 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4756 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4757 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4758 SUB #1,W \ decrement count loop
4759 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4760 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4761 0<> WHILE \ ----> out of loop ----+
4762 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4764 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4765 CMP Y,X \ 1 | cycle time out of bound ?
4767 BIC #$30,&RC5_TIM_CTL \ | | stop timer
4768 GOTO FW1 \ | | quit on truncated RC5 message
4770 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4772 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4773 \ ******************************\ |
4774 \ RC5_SampleEndOf: \ <---------------------+
4775 \ ******************************\
4776 BIC #$30,&RC5_TIM_CTL \ stop timer
4777 \ ******************************\
4778 \ RC5_ComputeNewRC5word \
4779 \ ******************************\
4780 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4781 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4782 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4783 \ ******************************\
4784 \ RC5_ComputeC6bit \
4785 \ ******************************\
4786 BIT #BIT14,T \ test /C6 bit in T
4787 0= IF BIS #BIT6,X \ set C6 bit in X
4788 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4789 \ ******************************\
4790 \ RC5_CommandByteIsDone \ -- BASE RC5_code
4791 \ ******************************\
4792 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
4793 \ ******************************\
4794 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4795 XOR @RSP,T \ (new XOR old) Toggle bits
4796 BIT #UF10,T \ repeated RC5_command ?
4797 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
4798 XOR #UF10,0(RSP) \ 5 toggle bit memory
4799 \ ******************************\
4800 \ Display IR_RC5 code \
4801 \ ******************************\
4802 SUB #8,PSP \ TOS -- x x x x TOS
4803 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
4804 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
4805 MOV #$10,&BASEADR \ set hexadecimal base
4806 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
4807 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
4808 LO2HI \ switch from assembler to FORTH
4809 LCD_CLEAR \ set LCD cursor at home
4810 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
4811 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4812 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
4813 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
4814 HI2LO \ -- switch from FORTH to assembler
4815 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
4816 MOV @PSP+,TOS \ -- TOS
4818 MOV @RSP+,SR \ restore SR flags
4819 BIC #%1111_1000,SR \ but force CPU Active Mode
4820 RET \ (instead of RETI)
4824 \ ------------------------------\
4825 HDNCODE STOP_R2L \ define new STOP_APP
4826 \ ------------------------------\
4827 CMP #RET_ADR,&{RC5TOLCD}+8 \
4828 0<> IF \ if previous START executing
4829 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
4830 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
4831 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
4832 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
4833 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
4834 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
4835 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
4836 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
4837 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
4838 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
4843 \ ------------------------------\
4845 \ ------------------------------\
4846 BW1 \ <-- INI_R2L for some events
4848 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4850 ." RC5toLCD is removed,"
4851 ." type START to restart"
4854 \ ------------------------------\
4856 \ ------------------------------\
4857 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
4858 \ ------------------------------\
4860 \ ------------------------------\
4861 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
4862 \ ------------------------------\
4863 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
4864 \ ------------------------------\
4865 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
4866 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
4868 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
4869 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
4871 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
4872 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
4873 \ CMP #4,TOS \ hardware RST
4874 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
4875 \ CMP #2,TOS \ Power_ON event
4876 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4878 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4880 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4882 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4883 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
4884 \ ------------------------------\
4885 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4886 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4887 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4888 \ -- \ID input divider \ 10 = /4
4889 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4890 \ - \TBCLR TimerB Clear
4893 \ -------------------------------\
4894 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4895 \ -- \CM Capture Mode
4900 \ --- \OUTMOD \ 011 = set/reset
4906 \ -------------------------------\
4908 \ -------------------------------\
4910 \ ------------------------------\
4911 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4912 \ ------------------------------\
4913 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4914 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4915 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4916 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4918 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4919 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4921 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4922 \ ------------------------------\
4923 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4924 \ ------------------------------\
4925 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4926 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4927 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4928 \ ------------------------------\
4929 BIS.B #LCDVo,&LCDVo_DIR \
4930 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4931 \ ------------------------------\
4932 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4933 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4934 \ ------------------------------\
4935 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4936 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4937 \ ******************************\
4939 \ ******************************\
4940 BIS.B #RC5,&IR_IE \ enable RC5_Int
4941 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4942 \ ******************************\
4943 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4944 \ ******************************\
4945 \ %01 0001 0100 \ TAxCTL
4946 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4947 \ -- \ ID divided by 1
4948 \ -- \ MC MODE = up to TAxCCRn
4949 \ - \ TACLR clear timer count
4952 \ ------------------------------\
4953 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4954 \ ------------------------------\
4956 \ --- \ TAIDEX pre divisor
4957 \ ------------------------------\
4958 \ %0000 0000 0000 0101 \ TAxCCR0
4959 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4960 \ ------------------------------\
4961 \ %0000 0000 0001 0000 \ TAxCCTL0
4962 \ - \ CAP capture/compare mode = compare
4965 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4966 \ ------------------------------\
4967 \ define LPM mode for ACCEPT \
4968 \ ------------------------------\
4969 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
4970 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4971 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4972 \ ------------------------------\
4974 \ ------------------------------\
4976 \ ------------------------------\
4977 #1000 20_US \ 1- wait 20 ms
4978 %011 TOP_LCD \ 2- send DB5=DB4=1
4979 #205 20_US \ 3- wait 4,1 ms
4980 %011 TOP_LCD \ 4- send again DB5=DB4=1
4981 #5 20_US \ 5- wait 0,1 ms
4982 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4983 #2 20_US \ wait 40 us = LCD cycle
4984 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4985 #2 20_US \ wait 40 us = LCD cycle
4986 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4987 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4988 LCD_CLEAR \ 10- "LCD_Clear"
4989 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4990 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4991 LCD_CLEAR \ 10- "LCD_Clear"
4992 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4993 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4994 CR ." I love you" \ display message on LCD
4995 ['] CR >BODY IS CR \ CR executes its default value
4996 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4997 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5000 \ ------------------------------\
5002 \ ------------------------------\
5003 CODE START \ this routine replaces WARM and COLD default values by these of this application.
5004 \ ------------------------------\
5005 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
5006 0= IF \ if not done, customizes MARKER_DOES
5007 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
5008 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
5009 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
5010 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
5011 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
5012 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
5013 MOV #RC5_INT,&IR_VEC \ init interrupt vector
5014 MOV #INI_R2L,PC \ then execute new INI_APP, without return
5018 \ ------------------------------\
5021 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
5023 MARKER {RC5TOLCD} \ restore the state before MARKER definition
5024 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
5025 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
5026 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
5027 \ {RC5TOLCD}+14: make room to save previous IR_VEC
5029 [UNDEFINED] CONSTANT [IF]
5030 \ https://forth-standard.org/standard/core/CONSTANT
5031 \ CONSTANT <name> n -- define a Forth CONSTANT
5035 MOV TOS,-2(W) \ PFA = n
5042 [UNDEFINED] STATE [IF]
5043 \ https://forth-standard.org/standard/core/STATE
5044 \ STATE -- a-addr holds compiler state
5045 STATEADR CONSTANT STATE
5049 \ https://forth-standard.org/standard/core/Equal
5050 \ = x1 x2 -- flag test x1=x2
5057 XOR #-1,TOS \ 1 flag Z = 1
5062 [UNDEFINED] IF [IF] \ define IF and THEN
5063 \ https://forth-standard.org/standard/core/IF
5064 \ IF -- IFadr initialize conditional forward branch
5068 MOV &DP,TOS \ -- HERE
5069 ADD #4,&DP \ compile one word, reserve one word
5070 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
5071 ADD #2,TOS \ -- HERE+2=IFadr
5075 \ https://forth-standard.org/standard/core/THEN
5076 \ THEN IFadr -- resolve forward branch
5077 CODE THEN \ immediate
5078 MOV &DP,0(TOS) \ -- IFadr
5084 [UNDEFINED] ELSE [IF]
5085 \ https://forth-standard.org/standard/core/ELSE
5086 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
5087 CODE ELSE \ immediate
5088 ADD #4,&DP \ make room to compile two words
5089 MOV &DP,W \ W=HERE+4
5091 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
5093 MOV W,TOS \ -- ELSEadr
5098 [UNDEFINED] IS [IF] \ define DEFER! and IS
5100 \ https://forth-standard.org/standard/core/DEFERStore
5101 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
5102 CODE DEFER! \ xt2 xt1 --
5103 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
5108 \ https://forth-standard.org/standard/core/IS
5111 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
5112 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
5113 \ or in a definition : ... ['] U. IS DISPLAY ...
5114 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
5116 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
5120 IF POSTPONE ['] POSTPONE DEFER!
5126 [UNDEFINED] >BODY [IF]
5127 \ https://forth-standard.org/standard/core/toBODY
5128 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
5135 \ CODE 20uS \ n -- 8MHz version
5136 \ BEGIN \ 4 + 16 ~ loop
5137 \ MOV #39,rDOCON \ 39
5144 \ MOV #XDOCON,rDOCON \ 2
5149 CODE 20_US \ n -- n * 20 us
5150 BEGIN \ here we presume that LCD_TIM_IFG = 1...
5152 BIT #1,&LCD_TIM_CTL \ 3
5153 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
5154 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
5156 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
5161 CODE TOP_LCD \ LCD Sample
5162 \ \ if write : %xxxx_WWWW --
5163 \ \ if read : -- %0000_RRRR
5164 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5165 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5166 0= IF \ write LCD bits pattern
5168 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5169 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5172 THEN \ read LCD bits pattern
5175 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5176 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5181 CODE LCD_WRC \ char -- Write Char
5182 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5184 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
5185 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
5186 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5187 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5188 COLON \ high level word starts here
5189 TOP_LCD 2 20_US \ write high nibble first
5193 CODE LCD_WRF \ func -- Write Fonction
5194 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5198 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5199 : LCD_HOME $02 LCD_WRF 100 20_us ;
5201 \ [UNDEFINED] OR [IF]
5203 \ \ https://forth-standard.org/standard/core/OR
5204 \ \ C OR x1 x2 -- x3 logical OR
5212 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5213 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5214 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5215 \ : LCD_FN_SET $20 OR LCD_WrF ;
5216 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5217 \ : LCD_GOTO $80 OR LCD_WrF ;
5220 \ CODE LCD_RDS \ -- status Read Status
5221 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5222 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5223 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5224 \ COLON \ starts a FORTH word
5225 \ TOP_LCD 2 20_us \ -- %0000_HHHH
5226 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
5227 \ HI2LO \ switch from FORTH to assembler
5228 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
5229 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
5230 \ MOV @RSP+,IP \ restore IP saved by COLON
5234 \ CODE LCD_RDC \ -- char Read Char
5235 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5240 \ ******************************\
5241 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5242 \ ******************************\
5243 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5244 BIT.B #SW2,&SW2_IN \ test switch S2
5245 0= IF \ case of switch S2 pressed
5246 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5248 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5251 BIT.B #SW1,&SW1_IN \ test switch S1 input
5252 0= IF \ case of Switch S1 pressed
5253 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5255 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5262 \ ******************************\
5263 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
5264 \ ******************************\
5265 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5266 \ ******************************\
5267 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5268 \ \ SMclock = 8|16|24 MHz
5269 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5270 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5271 \ \ SR(9)=new Toggle bit memory (ADD on)
5272 \ ******************************\
5273 \ RC5_FirstStartBitHalfCycle: \
5274 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5275 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5276 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5278 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5279 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5281 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5282 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5284 MOV #1778,X \ RC5_Period * 1us
5285 MOV #14,W \ count of loop
5287 \ ******************************\
5288 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5289 \ ******************************\ |
5290 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5291 \ RC5_Compute_3/4_Period: \ |
5292 RRUM #1,X \ X=1/2 cycle |
5295 ADD X,Y \ Y=3/4 cycle
5296 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5298 \ ******************************\
5299 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5300 \ ******************************\
5301 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5302 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5303 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5304 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5305 SUB #1,W \ decrement count loop
5306 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
5307 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5308 0<> WHILE \ ----> out of loop ----+
5309 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5311 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
5312 CMP Y,X \ 1 | cycle time out of bound ?
5314 BIC #$30,&RC5_TIM_CTL \ | | stop timer
5315 GOTO FW1 \ | | quit on truncated RC5 message
5317 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
5319 REPEAT \ ----> loop back --+ | with X = new RC5_period value
5320 \ ******************************\ |
5321 \ RC5_SampleEndOf: \ <---------------------+
5322 \ ******************************\
5323 BIC #$30,&RC5_TIM_CTL \ stop timer
5324 \ ******************************\
5325 \ RC5_ComputeNewRC5word \
5326 \ ******************************\
5327 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
5328 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
5329 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
5330 \ ******************************\
5331 \ RC5_ComputeC6bit \
5332 \ ******************************\
5333 BIT #BIT14,T \ test /C6 bit in T
5334 0= IF BIS #BIT6,X \ set C6 bit in X
5335 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
5336 \ ******************************\
5337 \ RC5_CommandByteIsDone \ -- BASE RC5_code
5338 \ ******************************\
5339 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
5340 \ ******************************\
5341 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
5342 XOR @RSP,T \ (new XOR old) Toggle bits
5343 BIT #UF10,T \ repeated RC5_command ?
5344 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
5345 XOR #UF10,0(RSP) \ 5 toggle bit memory
5346 \ ******************************\
5347 \ Display IR_RC5 code \
5348 \ ******************************\
5349 SUB #8,PSP \ TOS -- x x x x TOS
5350 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
5351 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
5352 MOV #$10,&BASEADR \ set hexadecimal base
5353 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
5354 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
5355 LO2HI \ switch from assembler to FORTH
5356 LCD_CLEAR \ set LCD cursor at home
5357 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
5358 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
5359 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
5360 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
5361 HI2LO \ -- switch from FORTH to assembler
5362 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
5363 MOV @PSP+,TOS \ -- TOS
5365 MOV @RSP+,SR \ restore SR flags
5366 BIC #%1111_1000,SR \ but force CPU Active Mode
5367 RET \ (instead of RETI)
5371 \ ------------------------------\
5372 HDNCODE STOP_R2L \ define new STOP_APP
5373 \ ------------------------------\
5374 CMP #RET_ADR,&{RC5TOLCD}+8 \
5375 0<> IF \ if previous START executing
5376 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
5377 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
5378 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
5379 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
5380 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
5381 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
5382 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
5383 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
5384 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
5385 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
5390 \ ------------------------------\
5392 \ ------------------------------\
5393 BW1 \ <-- INI_R2L for some events
5395 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
5397 ." RC5toLCD is removed,"
5398 ." type START to restart"
5401 \ ------------------------------\
5403 \ ------------------------------\
5404 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
5405 \ ------------------------------\
5407 \ ------------------------------\
5408 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
5409 \ ------------------------------\
5410 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
5411 \ ------------------------------\
5412 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
5413 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
5415 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
5416 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
5418 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
5419 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
5420 \ CMP #4,TOS \ hardware RST
5421 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
5422 \ CMP #2,TOS \ Power_ON event
5423 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
5425 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
5427 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
5429 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
5430 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
5431 \ ------------------------------\
5432 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
5433 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5434 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5435 \ -- \ID input divider \ 10 = /4
5436 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
5437 \ - \TBCLR TimerB Clear
5440 \ -------------------------------\
5441 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5442 \ -- \CM Capture Mode
5447 \ --- \OUTMOD \ 011 = set/reset
5453 \ -------------------------------\
5455 \ -------------------------------\
5457 \ ------------------------------\
5458 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
5459 \ ------------------------------\
5460 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
5461 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
5462 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
5463 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
5465 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
5466 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
5468 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
5469 \ ------------------------------\
5470 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
5471 \ ------------------------------\
5472 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
5473 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
5474 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5475 \ ------------------------------\
5476 BIS.B #LCDVo,&LCDVo_DIR \
5477 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
5478 \ ------------------------------\
5479 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5480 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5481 \ ------------------------------\
5482 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5483 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5484 \ ******************************\
5486 \ ******************************\
5487 BIS.B #RC5,&IR_IE \ enable RC5_Int
5488 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5489 \ ******************************\
5490 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
5491 \ ******************************\
5492 \ %01 0001 0100 \ TAxCTL
5493 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
5494 \ -- \ ID divided by 1
5495 \ -- \ MC MODE = up to TAxCCRn
5496 \ - \ TACLR clear timer count
5499 \ ------------------------------\
5500 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
5501 \ ------------------------------\
5503 \ --- \ TAIDEX pre divisor
5504 \ ------------------------------\
5505 \ %0000 0000 0000 0101 \ TAxCCR0
5506 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
5507 \ ------------------------------\
5508 \ %0000 0000 0001 0000 \ TAxCCTL0
5509 \ - \ CAP capture/compare mode = compare
5512 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
5513 \ ------------------------------\
5514 \ define LPM mode for ACCEPT \
5515 \ ------------------------------\
5516 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
5517 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5518 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5519 \ ------------------------------\
5521 \ ------------------------------\
5523 \ ------------------------------\
5524 #1000 20_US \ 1- wait 20 ms
5525 %011 TOP_LCD \ 2- send DB5=DB4=1
5526 #205 20_US \ 3- wait 4,1 ms
5527 %011 TOP_LCD \ 4- send again DB5=DB4=1
5528 #5 20_US \ 5- wait 0,1 ms
5529 %011 TOP_LCD \ 6- send again again DB5=DB4=1
5530 #2 20_US \ wait 40 us = LCD cycle
5531 %010 TOP_LCD \ 7- send DB5=1 DB4=0
5532 #2 20_US \ wait 40 us = LCD cycle
5533 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5534 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5535 LCD_CLEAR \ 10- "LCD_Clear"
5536 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5537 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5538 LCD_CLEAR \ 10- "LCD_Clear"
5539 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5540 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5541 CR ." I love you" \ display message on LCD
5542 ['] CR >BODY IS CR \ CR executes its default value
5543 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
5544 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5547 \ ------------------------------\
5549 \ ------------------------------\
5550 CODE START \ this routine replaces WARM and COLD default values by these of this application.
5551 \ ------------------------------\
5552 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
5553 0= IF \ if not done, customizes MARKER_DOES
5554 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
5555 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
5556 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
5557 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
5558 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
5559 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
5560 MOV #RC5_INT,&IR_VEC \ init interrupt vector
5561 MOV #INI_R2L,PC \ then execute new INI_APP, without return
5565 \ ------------------------------\
5568 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
5570 MARKER {RC5TOLCD} \ restore the state before MARKER definition
5571 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
5572 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
5573 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
5574 \ {RC5TOLCD}+14: make room to save previous IR_VEC
5576 [UNDEFINED] CONSTANT [IF]
5577 \ https://forth-standard.org/standard/core/CONSTANT
5578 \ CONSTANT <name> n -- define a Forth CONSTANT
5582 MOV TOS,-2(W) \ PFA = n
5589 [UNDEFINED] STATE [IF]
5590 \ https://forth-standard.org/standard/core/STATE
5591 \ STATE -- a-addr holds compiler state
5592 STATEADR CONSTANT STATE
5596 \ https://forth-standard.org/standard/core/Equal
5597 \ = x1 x2 -- flag test x1=x2
5604 XOR #-1,TOS \ 1 flag Z = 1
5609 [UNDEFINED] IF [IF] \ define IF and THEN
5610 \ https://forth-standard.org/standard/core/IF
5611 \ IF -- IFadr initialize conditional forward branch
5615 MOV &DP,TOS \ -- HERE
5616 ADD #4,&DP \ compile one word, reserve one word
5617 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
5618 ADD #2,TOS \ -- HERE+2=IFadr
5622 \ https://forth-standard.org/standard/core/THEN
5623 \ THEN IFadr -- resolve forward branch
5624 CODE THEN \ immediate
5625 MOV &DP,0(TOS) \ -- IFadr
5631 [UNDEFINED] ELSE [IF]
5632 \ https://forth-standard.org/standard/core/ELSE
5633 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
5634 CODE ELSE \ immediate
5635 ADD #4,&DP \ make room to compile two words
5636 MOV &DP,W \ W=HERE+4
5638 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
5640 MOV W,TOS \ -- ELSEadr
5645 [UNDEFINED] IS [IF] \ define DEFER! and IS
5647 \ https://forth-standard.org/standard/core/DEFERStore
5648 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
5649 CODE DEFER! \ xt2 xt1 --
5650 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
5655 \ https://forth-standard.org/standard/core/IS
5658 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
5659 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
5660 \ or in a definition : ... ['] U. IS DISPLAY ...
5661 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
5663 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
5667 IF POSTPONE ['] POSTPONE DEFER!
5673 [UNDEFINED] >BODY [IF]
5674 \ https://forth-standard.org/standard/core/toBODY
5675 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
5682 \ CODE 20uS \ n -- 8MHz version
5683 \ BEGIN \ 4 + 16 ~ loop
5684 \ MOV #39,rDOCON \ 39
5691 \ MOV #XDOCON,rDOCON \ 2
5696 CODE 20_US \ n -- n * 20 us
5697 BEGIN \ here we presume that LCD_TIM_IFG = 1...
5699 BIT #1,&LCD_TIM_CTL \ 3
5700 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
5701 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
5703 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
5708 CODE TOP_LCD \ LCD Sample
5709 \ \ if write : %xxxx_WWWW --
5710 \ \ if read : -- %0000_RRRR
5711 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5712 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5713 0= IF \ write LCD bits pattern
5715 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5716 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5719 THEN \ read LCD bits pattern
5722 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5723 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5728 CODE LCD_WRC \ char -- Write Char
5729 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5731 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
5732 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
5733 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5734 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5735 COLON \ high level word starts here
5736 TOP_LCD 2 20_US \ write high nibble first
5740 CODE LCD_WRF \ func -- Write Fonction
5741 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5745 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5746 : LCD_HOME $02 LCD_WRF 100 20_us ;
5748 \ [UNDEFINED] OR [IF]
5750 \ \ https://forth-standard.org/standard/core/OR
5751 \ \ C OR x1 x2 -- x3 logical OR
5759 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5760 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5761 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5762 \ : LCD_FN_SET $20 OR LCD_WrF ;
5763 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5764 \ : LCD_GOTO $80 OR LCD_WrF ;
5767 \ CODE LCD_RDS \ -- status Read Status
5768 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5769 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5770 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5771 \ COLON \ starts a FORTH word
5772 \ TOP_LCD 2 20_us \ -- %0000_HHHH
5773 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
5774 \ HI2LO \ switch from FORTH to assembler
5775 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
5776 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
5777 \ MOV @RSP+,IP \ restore IP saved by COLON
5781 \ CODE LCD_RDC \ -- char Read Char
5782 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5787 \ ******************************\
5788 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5789 \ ******************************\
5790 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5791 BIT.B #SW2,&SW2_IN \ test switch S2
5792 0= IF \ case of switch S2 pressed
5793 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5795 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5798 BIT.B #SW1,&SW1_IN \ test switch S1 input
5799 0= IF \ case of Switch S1 pressed
5800 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5802 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5809 \ ******************************\
5810 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
5811 \ ******************************\
5812 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5813 \ ******************************\
5814 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5815 \ \ SMclock = 8|16|24 MHz
5816 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5817 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5818 \ \ SR(9)=new Toggle bit memory (ADD on)
5819 \ ******************************\
5820 \ RC5_FirstStartBitHalfCycle: \
5821 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5822 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5823 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5825 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5826 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5828 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5829 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5831 MOV #1778,X \ RC5_Period * 1us
5832 MOV #14,W \ count of loop
5834 \ ******************************\
5835 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5836 \ ******************************\ |
5837 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5838 \ RC5_Compute_3/4_Period: \ |
5839 RRUM #1,X \ X=1/2 cycle |
5842 ADD X,Y \ Y=3/4 cycle
5843 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5845 \ ******************************\
5846 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5847 \ ******************************\
5848 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5849 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5850 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5851 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5852 SUB #1,W \ decrement count loop
5853 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
5854 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5855 0<> WHILE \ ----> out of loop ----+
5856 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5858 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
5859 CMP Y,X \ 1 | cycle time out of bound ?
5861 BIC #$30,&RC5_TIM_CTL \ | | stop timer
5862 GOTO FW1 \ | | quit on truncated RC5 message
5864 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
5866 REPEAT \ ----> loop back --+ | with X = new RC5_period value
5867 \ ******************************\ |
5868 \ RC5_SampleEndOf: \ <---------------------+
5869 \ ******************************\
5870 BIC #$30,&RC5_TIM_CTL \ stop timer
5871 \ ******************************\
5872 \ RC5_ComputeNewRC5word \
5873 \ ******************************\
5874 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
5875 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
5876 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
5877 \ ******************************\
5878 \ RC5_ComputeC6bit \
5879 \ ******************************\
5880 BIT #BIT14,T \ test /C6 bit in T
5881 0= IF BIS #BIT6,X \ set C6 bit in X
5882 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
5883 \ ******************************\
5884 \ RC5_CommandByteIsDone \ -- BASE RC5_code
5885 \ ******************************\
5886 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
5887 \ ******************************\
5888 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
5889 XOR @RSP,T \ (new XOR old) Toggle bits
5890 BIT #UF10,T \ repeated RC5_command ?
5891 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
5892 XOR #UF10,0(RSP) \ 5 toggle bit memory
5893 \ ******************************\
5894 \ Display IR_RC5 code \
5895 \ ******************************\
5896 SUB #8,PSP \ TOS -- x x x x TOS
5897 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
5898 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
5899 MOV #$10,&BASEADR \ set hexadecimal base
5900 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
5901 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
5902 LO2HI \ switch from assembler to FORTH
5903 LCD_CLEAR \ set LCD cursor at home
5904 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
5905 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
5906 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
5907 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
5908 HI2LO \ -- switch from FORTH to assembler
5909 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
5910 MOV @PSP+,TOS \ -- TOS
5912 MOV @RSP+,SR \ restore SR flags
5913 BIC #%1111_1000,SR \ but force CPU Active Mode
5914 RET \ (instead of RETI)
5918 \ ------------------------------\
5919 HDNCODE STOP_R2L \ define new STOP_APP
5920 \ ------------------------------\
5921 CMP #RET_ADR,&{RC5TOLCD}+8 \
5922 0<> IF \ if previous START executing
5923 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
5924 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
5925 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
5926 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
5927 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
5928 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
5929 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
5930 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
5931 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
5932 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
5937 \ ------------------------------\
5939 \ ------------------------------\
5940 BW1 \ <-- INI_R2L for some events
5942 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
5944 ." RC5toLCD is removed,"
5945 ." type START to restart"
5948 \ ------------------------------\
5950 \ ------------------------------\
5951 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
5952 \ ------------------------------\
5954 \ ------------------------------\
5955 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
5956 \ ------------------------------\
5957 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
5958 \ ------------------------------\
5959 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
5960 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
5962 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
5963 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
5965 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
5966 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
5967 \ CMP #4,TOS \ hardware RST
5968 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
5969 \ CMP #2,TOS \ Power_ON event
5970 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
5972 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
5974 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
5976 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
5977 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
5978 \ ------------------------------\
5979 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
5980 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5981 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5982 \ -- \ID input divider \ 10 = /4
5983 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
5984 \ - \TBCLR TimerB Clear
5987 \ -------------------------------\
5988 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5989 \ -- \CM Capture Mode
5994 \ --- \OUTMOD \ 011 = set/reset
6000 \ -------------------------------\
6002 \ -------------------------------\
6004 \ ------------------------------\
6005 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6006 \ ------------------------------\
6007 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6008 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6009 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6010 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6012 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6013 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6015 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6016 \ ------------------------------\
6017 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6018 \ ------------------------------\
6019 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6020 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6021 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6022 \ ------------------------------\
6023 BIS.B #LCDVo,&LCDVo_DIR \
6024 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6025 \ ------------------------------\
6026 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6027 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6028 \ ------------------------------\
6029 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6030 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6031 \ ******************************\
6033 \ ******************************\
6034 BIS.B #RC5,&IR_IE \ enable RC5_Int
6035 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6036 \ ******************************\
6037 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6038 \ ******************************\
6039 \ %01 0001 0100 \ TAxCTL
6040 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6041 \ -- \ ID divided by 1
6042 \ -- \ MC MODE = up to TAxCCRn
6043 \ - \ TACLR clear timer count
6046 \ ------------------------------\
6047 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6048 \ ------------------------------\
6050 \ --- \ TAIDEX pre divisor
6051 \ ------------------------------\
6052 \ %0000 0000 0000 0101 \ TAxCCR0
6053 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6054 \ ------------------------------\
6055 \ %0000 0000 0001 0000 \ TAxCCTL0
6056 \ - \ CAP capture/compare mode = compare
6059 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6060 \ ------------------------------\
6061 \ define LPM mode for ACCEPT \
6062 \ ------------------------------\
6063 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
6064 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6065 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6066 \ ------------------------------\
6068 \ ------------------------------\
6070 \ ------------------------------\
6071 #1000 20_US \ 1- wait 20 ms
6072 %011 TOP_LCD \ 2- send DB5=DB4=1
6073 #205 20_US \ 3- wait 4,1 ms
6074 %011 TOP_LCD \ 4- send again DB5=DB4=1
6075 #5 20_US \ 5- wait 0,1 ms
6076 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6077 #2 20_US \ wait 40 us = LCD cycle
6078 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6079 #2 20_US \ wait 40 us = LCD cycle
6080 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6081 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6082 LCD_CLEAR \ 10- "LCD_Clear"
6083 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6084 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6085 LCD_CLEAR \ 10- "LCD_Clear"
6086 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6087 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6088 CR ." I love you" \ display message on LCD
6089 ['] CR >BODY IS CR \ CR executes its default value
6090 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
6091 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6094 \ ------------------------------\
6096 \ ------------------------------\
6097 CODE START \ this routine replaces WARM and COLD default values by these of this application.
6098 \ ------------------------------\
6099 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
6100 0= IF \ if not done, customizes MARKER_DOES
6101 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
6102 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
6103 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
6104 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
6105 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6106 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
6107 MOV #RC5_INT,&IR_VEC \ init interrupt vector
6108 MOV #INI_R2L,PC \ then execute new INI_APP, without return
6112 \ ------------------------------\
6115 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
6117 MARKER {RC5TOLCD} \ restore the state before MARKER definition
6118 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
6119 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
6120 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
6121 \ {RC5TOLCD}+14: make room to save previous IR_VEC
6123 [UNDEFINED] CONSTANT [IF]
6124 \ https://forth-standard.org/standard/core/CONSTANT
6125 \ CONSTANT <name> n -- define a Forth CONSTANT
6129 MOV TOS,-2(W) \ PFA = n
6136 [UNDEFINED] STATE [IF]
6137 \ https://forth-standard.org/standard/core/STATE
6138 \ STATE -- a-addr holds compiler state
6139 STATEADR CONSTANT STATE
6143 \ https://forth-standard.org/standard/core/Equal
6144 \ = x1 x2 -- flag test x1=x2
6151 XOR #-1,TOS \ 1 flag Z = 1
6156 [UNDEFINED] IF [IF] \ define IF and THEN
6157 \ https://forth-standard.org/standard/core/IF
6158 \ IF -- IFadr initialize conditional forward branch
6162 MOV &DP,TOS \ -- HERE
6163 ADD #4,&DP \ compile one word, reserve one word
6164 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
6165 ADD #2,TOS \ -- HERE+2=IFadr
6169 \ https://forth-standard.org/standard/core/THEN
6170 \ THEN IFadr -- resolve forward branch
6171 CODE THEN \ immediate
6172 MOV &DP,0(TOS) \ -- IFadr
6178 [UNDEFINED] ELSE [IF]
6179 \ https://forth-standard.org/standard/core/ELSE
6180 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
6181 CODE ELSE \ immediate
6182 ADD #4,&DP \ make room to compile two words
6183 MOV &DP,W \ W=HERE+4
6185 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
6187 MOV W,TOS \ -- ELSEadr
6192 [UNDEFINED] IS [IF] \ define DEFER! and IS
6194 \ https://forth-standard.org/standard/core/DEFERStore
6195 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
6196 CODE DEFER! \ xt2 xt1 --
6197 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
6202 \ https://forth-standard.org/standard/core/IS
6205 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
6206 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
6207 \ or in a definition : ... ['] U. IS DISPLAY ...
6208 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
6210 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
6214 IF POSTPONE ['] POSTPONE DEFER!
6220 [UNDEFINED] >BODY [IF]
6221 \ https://forth-standard.org/standard/core/toBODY
6222 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
6229 \ CODE 20uS \ n -- 8MHz version
6230 \ BEGIN \ 4 + 16 ~ loop
6231 \ MOV #39,rDOCON \ 39
6238 \ MOV #XDOCON,rDOCON \ 2
6243 CODE 20_US \ n -- n * 20 us
6244 BEGIN \ here we presume that LCD_TIM_IFG = 1...
6246 BIT #1,&LCD_TIM_CTL \ 3
6247 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
6248 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
6250 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
6255 CODE TOP_LCD \ LCD Sample
6256 \ \ if write : %xxxx_WWWW --
6257 \ \ if read : -- %0000_RRRR
6258 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6259 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6260 0= IF \ write LCD bits pattern
6262 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6263 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6266 THEN \ read LCD bits pattern
6269 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6270 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6275 CODE LCD_WRC \ char -- Write Char
6276 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6278 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
6279 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
6280 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6281 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6282 COLON \ high level word starts here
6283 TOP_LCD 2 20_US \ write high nibble first
6287 CODE LCD_WRF \ func -- Write Fonction
6288 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6292 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
6293 : LCD_HOME $02 LCD_WRF 100 20_us ;
6295 \ [UNDEFINED] OR [IF]
6297 \ \ https://forth-standard.org/standard/core/OR
6298 \ \ C OR x1 x2 -- x3 logical OR
6306 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
6307 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
6308 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
6309 \ : LCD_FN_SET $20 OR LCD_WrF ;
6310 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
6311 \ : LCD_GOTO $80 OR LCD_WrF ;
6314 \ CODE LCD_RDS \ -- status Read Status
6315 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6316 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6317 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6318 \ COLON \ starts a FORTH word
6319 \ TOP_LCD 2 20_us \ -- %0000_HHHH
6320 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
6321 \ HI2LO \ switch from FORTH to assembler
6322 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
6323 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
6324 \ MOV @RSP+,IP \ restore IP saved by COLON
6328 \ CODE LCD_RDC \ -- char Read Char
6329 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6334 \ ******************************\
6335 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6336 \ ******************************\
6337 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
6338 BIT.B #SW2,&SW2_IN \ test switch S2
6339 0= IF \ case of switch S2 pressed
6340 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
6342 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
6345 BIT.B #SW1,&SW1_IN \ test switch S1 input
6346 0= IF \ case of Switch S1 pressed
6347 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
6349 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
6356 \ ******************************\
6357 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
6358 \ ******************************\
6359 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6360 \ ******************************\
6361 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6362 \ \ SMclock = 8|16|24 MHz
6363 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
6364 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
6365 \ \ SR(9)=new Toggle bit memory (ADD on)
6366 \ ******************************\
6367 \ RC5_FirstStartBitHalfCycle: \
6368 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
6369 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
6370 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
6372 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
6373 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
6375 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
6376 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
6378 MOV #1778,X \ RC5_Period * 1us
6379 MOV #14,W \ count of loop
6381 \ ******************************\
6382 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
6383 \ ******************************\ |
6384 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
6385 \ RC5_Compute_3/4_Period: \ |
6386 RRUM #1,X \ X=1/2 cycle |
6389 ADD X,Y \ Y=3/4 cycle
6390 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
6392 \ ******************************\
6393 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
6394 \ ******************************\
6395 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6396 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
6397 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6398 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6399 SUB #1,W \ decrement count loop
6400 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
6401 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6402 0<> WHILE \ ----> out of loop ----+
6403 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6405 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
6406 CMP Y,X \ 1 | cycle time out of bound ?
6408 BIC #$30,&RC5_TIM_CTL \ | | stop timer
6409 GOTO FW1 \ | | quit on truncated RC5 message
6411 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
6413 REPEAT \ ----> loop back --+ | with X = new RC5_period value
6414 \ ******************************\ |
6415 \ RC5_SampleEndOf: \ <---------------------+
6416 \ ******************************\
6417 BIC #$30,&RC5_TIM_CTL \ stop timer
6418 \ ******************************\
6419 \ RC5_ComputeNewRC5word \
6420 \ ******************************\
6421 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
6422 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
6423 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
6424 \ ******************************\
6425 \ RC5_ComputeC6bit \
6426 \ ******************************\
6427 BIT #BIT14,T \ test /C6 bit in T
6428 0= IF BIS #BIT6,X \ set C6 bit in X
6429 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
6430 \ ******************************\
6431 \ RC5_CommandByteIsDone \ -- BASE RC5_code
6432 \ ******************************\
6433 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
6434 \ ******************************\
6435 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
6436 XOR @RSP,T \ (new XOR old) Toggle bits
6437 BIT #UF10,T \ repeated RC5_command ?
6438 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
6439 XOR #UF10,0(RSP) \ 5 toggle bit memory
6440 \ ******************************\
6441 \ Display IR_RC5 code \
6442 \ ******************************\
6443 SUB #8,PSP \ TOS -- x x x x TOS
6444 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6445 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6446 MOV #$10,&BASEADR \ set hexadecimal base
6447 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6448 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6449 LO2HI \ switch from assembler to FORTH
6450 LCD_CLEAR \ set LCD cursor at home
6451 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6452 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
6453 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
6454 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
6455 HI2LO \ -- switch from FORTH to assembler
6456 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
6457 MOV @PSP+,TOS \ -- TOS
6459 MOV @RSP+,SR \ restore SR flags
6460 BIC #%1111_1000,SR \ but force CPU Active Mode
6461 RET \ (instead of RETI)
6465 \ ------------------------------\
6466 HDNCODE STOP_R2L \ define new STOP_APP
6467 \ ------------------------------\
6468 CMP #RET_ADR,&{RC5TOLCD}+8 \
6469 0<> IF \ if previous START executing
6470 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
6471 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
6472 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
6473 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
6474 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
6475 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
6476 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
6477 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
6478 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
6479 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
6484 \ ------------------------------\
6486 \ ------------------------------\
6487 BW1 \ <-- INI_R2L for some events
6489 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
6491 ." RC5toLCD is removed,"
6492 ." type START to restart"
6495 \ ------------------------------\
6497 \ ------------------------------\
6498 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
6499 \ ------------------------------\
6501 \ ------------------------------\
6502 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
6503 \ ------------------------------\
6504 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
6505 \ ------------------------------\
6506 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
6507 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
6509 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
6510 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
6512 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
6513 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
6514 \ CMP #4,TOS \ hardware RST
6515 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
6516 \ CMP #2,TOS \ Power_ON event
6517 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
6519 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
6521 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
6523 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
6524 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
6525 \ ------------------------------\
6526 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
6527 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6528 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6529 \ -- \ID input divider \ 10 = /4
6530 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6531 \ - \TBCLR TimerB Clear
6534 \ -------------------------------\
6535 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6536 \ -- \CM Capture Mode
6541 \ --- \OUTMOD \ 011 = set/reset
6547 \ -------------------------------\
6549 \ -------------------------------\
6551 \ ------------------------------\
6552 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6553 \ ------------------------------\
6554 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6555 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6556 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6557 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6559 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6560 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6562 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6563 \ ------------------------------\
6564 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6565 \ ------------------------------\
6566 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6567 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6568 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6569 \ ------------------------------\
6570 BIS.B #LCDVo,&LCDVo_DIR \
6571 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6572 \ ------------------------------\
6573 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6574 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6575 \ ------------------------------\
6576 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6577 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6578 \ ******************************\
6580 \ ******************************\
6581 BIS.B #RC5,&IR_IE \ enable RC5_Int
6582 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6583 \ ******************************\
6584 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6585 \ ******************************\
6586 \ %01 0001 0100 \ TAxCTL
6587 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6588 \ -- \ ID divided by 1
6589 \ -- \ MC MODE = up to TAxCCRn
6590 \ - \ TACLR clear timer count
6593 \ ------------------------------\
6594 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6595 \ ------------------------------\
6597 \ --- \ TAIDEX pre divisor
6598 \ ------------------------------\
6599 \ %0000 0000 0000 0101 \ TAxCCR0
6600 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6601 \ ------------------------------\
6602 \ %0000 0000 0001 0000 \ TAxCCTL0
6603 \ - \ CAP capture/compare mode = compare
6606 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6607 \ ------------------------------\
6608 \ define LPM mode for ACCEPT \
6609 \ ------------------------------\
6610 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
6611 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6612 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6613 \ ------------------------------\
6615 \ ------------------------------\
6617 \ ------------------------------\
6618 #1000 20_US \ 1- wait 20 ms
6619 %011 TOP_LCD \ 2- send DB5=DB4=1
6620 #205 20_US \ 3- wait 4,1 ms
6621 %011 TOP_LCD \ 4- send again DB5=DB4=1
6622 #5 20_US \ 5- wait 0,1 ms
6623 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6624 #2 20_US \ wait 40 us = LCD cycle
6625 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6626 #2 20_US \ wait 40 us = LCD cycle
6627 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6628 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6629 LCD_CLEAR \ 10- "LCD_Clear"
6630 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6631 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6632 LCD_CLEAR \ 10- "LCD_Clear"
6633 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6634 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6635 CR ." I love you" \ display message on LCD
6636 ['] CR >BODY IS CR \ CR executes its default value
6637 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
6638 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6641 \ ------------------------------\
6643 \ ------------------------------\
6644 CODE START \ this routine replaces WARM and COLD default values by these of this application.
6645 \ ------------------------------\
6646 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
6647 0= IF \ if not done, customizes MARKER_DOES
6648 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
6649 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
6650 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
6651 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
6652 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6653 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
6654 MOV #RC5_INT,&IR_VEC \ init interrupt vector
6655 MOV #INI_R2L,PC \ then execute new INI_APP, without return
6659 \ ------------------------------\
6662 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
6664 MARKER {RC5TOLCD} \ restore the state before MARKER definition
6665 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
6666 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
6667 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
6668 \ {RC5TOLCD}+14: make room to save previous IR_VEC
6670 [UNDEFINED] CONSTANT [IF]
6671 \ https://forth-standard.org/standard/core/CONSTANT
6672 \ CONSTANT <name> n -- define a Forth CONSTANT
6676 MOV TOS,-2(W) \ PFA = n
6683 [UNDEFINED] STATE [IF]
6684 \ https://forth-standard.org/standard/core/STATE
6685 \ STATE -- a-addr holds compiler state
6686 STATEADR CONSTANT STATE
6690 \ https://forth-standard.org/standard/core/Equal
6691 \ = x1 x2 -- flag test x1=x2
6698 XOR #-1,TOS \ 1 flag Z = 1
6703 [UNDEFINED] IF [IF] \ define IF and THEN
6704 \ https://forth-standard.org/standard/core/IF
6705 \ IF -- IFadr initialize conditional forward branch
6709 MOV &DP,TOS \ -- HERE
6710 ADD #4,&DP \ compile one word, reserve one word
6711 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
6712 ADD #2,TOS \ -- HERE+2=IFadr
6716 \ https://forth-standard.org/standard/core/THEN
6717 \ THEN IFadr -- resolve forward branch
6718 CODE THEN \ immediate
6719 MOV &DP,0(TOS) \ -- IFadr
6725 [UNDEFINED] ELSE [IF]
6726 \ https://forth-standard.org/standard/core/ELSE
6727 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
6728 CODE ELSE \ immediate
6729 ADD #4,&DP \ make room to compile two words
6730 MOV &DP,W \ W=HERE+4
6732 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
6734 MOV W,TOS \ -- ELSEadr
6739 [UNDEFINED] IS [IF] \ define DEFER! and IS
6741 \ https://forth-standard.org/standard/core/DEFERStore
6742 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
6743 CODE DEFER! \ xt2 xt1 --
6744 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
6749 \ https://forth-standard.org/standard/core/IS
6752 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
6753 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
6754 \ or in a definition : ... ['] U. IS DISPLAY ...
6755 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
6757 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
6761 IF POSTPONE ['] POSTPONE DEFER!
6767 [UNDEFINED] >BODY [IF]
6768 \ https://forth-standard.org/standard/core/toBODY
6769 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
6776 \ CODE 20uS \ n -- 8MHz version
6777 \ BEGIN \ 4 + 16 ~ loop
6778 \ MOV #39,rDOCON \ 39
6785 \ MOV #XDOCON,rDOCON \ 2
6790 CODE 20_US \ n -- n * 20 us
6791 BEGIN \ here we presume that LCD_TIM_IFG = 1...
6793 BIT #1,&LCD_TIM_CTL \ 3
6794 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
6795 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
6797 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
6802 CODE TOP_LCD \ LCD Sample
6803 \ \ if write : %xxxx_WWWW --
6804 \ \ if read : -- %0000_RRRR
6805 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6806 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6807 0= IF \ write LCD bits pattern
6809 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6810 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6813 THEN \ read LCD bits pattern
6816 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6817 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6822 CODE LCD_WRC \ char -- Write Char
6823 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6825 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
6826 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
6827 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6828 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6829 COLON \ high level word starts here
6830 TOP_LCD 2 20_US \ write high nibble first
6834 CODE LCD_WRF \ func -- Write Fonction
6835 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6839 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
6840 : LCD_HOME $02 LCD_WRF 100 20_us ;
6842 \ [UNDEFINED] OR [IF]
6844 \ \ https://forth-standard.org/standard/core/OR
6845 \ \ C OR x1 x2 -- x3 logical OR
6853 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
6854 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
6855 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
6856 \ : LCD_FN_SET $20 OR LCD_WrF ;
6857 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
6858 \ : LCD_GOTO $80 OR LCD_WrF ;
6861 \ CODE LCD_RDS \ -- status Read Status
6862 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6863 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6864 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6865 \ COLON \ starts a FORTH word
6866 \ TOP_LCD 2 20_us \ -- %0000_HHHH
6867 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
6868 \ HI2LO \ switch from FORTH to assembler
6869 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
6870 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
6871 \ MOV @RSP+,IP \ restore IP saved by COLON
6875 \ CODE LCD_RDC \ -- char Read Char
6876 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6881 \ ******************************\
6882 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6883 \ ******************************\
6884 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
6885 BIT.B #SW2,&SW2_IN \ test switch S2
6886 0= IF \ case of switch S2 pressed
6887 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
6889 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
6892 BIT.B #SW1,&SW1_IN \ test switch S1 input
6893 0= IF \ case of Switch S1 pressed
6894 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
6896 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
6903 \ ******************************\
6904 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
6905 \ ******************************\
6906 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6907 \ ******************************\
6908 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6909 \ \ SMclock = 8|16|24 MHz
6910 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
6911 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
6912 \ \ SR(9)=new Toggle bit memory (ADD on)
6913 \ ******************************\
6914 \ RC5_FirstStartBitHalfCycle: \
6915 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
6916 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
6917 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
6919 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
6920 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
6922 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
6923 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
6925 MOV #1778,X \ RC5_Period * 1us
6926 MOV #14,W \ count of loop
6928 \ ******************************\
6929 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
6930 \ ******************************\ |
6931 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
6932 \ RC5_Compute_3/4_Period: \ |
6933 RRUM #1,X \ X=1/2 cycle |
6936 ADD X,Y \ Y=3/4 cycle
6937 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
6939 \ ******************************\
6940 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
6941 \ ******************************\
6942 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6943 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
6944 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6945 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6946 SUB #1,W \ decrement count loop
6947 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
6948 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6949 0<> WHILE \ ----> out of loop ----+
6950 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6952 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
6953 CMP Y,X \ 1 | cycle time out of bound ?
6955 BIC #$30,&RC5_TIM_CTL \ | | stop timer
6956 GOTO FW1 \ | | quit on truncated RC5 message
6958 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
6960 REPEAT \ ----> loop back --+ | with X = new RC5_period value
6961 \ ******************************\ |
6962 \ RC5_SampleEndOf: \ <---------------------+
6963 \ ******************************\
6964 BIC #$30,&RC5_TIM_CTL \ stop timer
6965 \ ******************************\
6966 \ RC5_ComputeNewRC5word \
6967 \ ******************************\
6968 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
6969 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
6970 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
6971 \ ******************************\
6972 \ RC5_ComputeC6bit \
6973 \ ******************************\
6974 BIT #BIT14,T \ test /C6 bit in T
6975 0= IF BIS #BIT6,X \ set C6 bit in X
6976 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
6977 \ ******************************\
6978 \ RC5_CommandByteIsDone \ -- BASE RC5_code
6979 \ ******************************\
6980 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
6981 \ ******************************\
6982 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
6983 XOR @RSP,T \ (new XOR old) Toggle bits
6984 BIT #UF10,T \ repeated RC5_command ?
6985 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
6986 XOR #UF10,0(RSP) \ 5 toggle bit memory
6987 \ ******************************\
6988 \ Display IR_RC5 code \
6989 \ ******************************\
6990 SUB #8,PSP \ TOS -- x x x x TOS
6991 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6992 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6993 MOV #$10,&BASEADR \ set hexadecimal base
6994 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6995 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6996 LO2HI \ switch from assembler to FORTH
6997 LCD_CLEAR \ set LCD cursor at home
6998 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6999 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
7000 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
7001 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
7002 HI2LO \ -- switch from FORTH to assembler
7003 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
7004 MOV @PSP+,TOS \ -- TOS
7006 MOV @RSP+,SR \ restore SR flags
7007 BIC #%1111_1000,SR \ but force CPU Active Mode
7008 RET \ (instead of RETI)
7012 \ ------------------------------\
7013 HDNCODE STOP_R2L \ define new STOP_APP
7014 \ ------------------------------\
7015 CMP #RET_ADR,&{RC5TOLCD}+8 \
7016 0<> IF \ if previous START executing
7017 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
7018 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
7019 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
7020 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
7021 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
7022 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
7023 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
7024 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
7025 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
7026 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
7031 \ ------------------------------\
7033 \ ------------------------------\
7034 BW1 \ <-- INI_R2L for some events
7036 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
7038 ." RC5toLCD is removed,"
7039 ." type START to restart"
7042 \ ------------------------------\
7044 \ ------------------------------\
7045 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
7046 \ ------------------------------\
7048 \ ------------------------------\
7049 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
7050 \ ------------------------------\
7051 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
7052 \ ------------------------------\
7053 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
7054 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
7056 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
7057 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
7059 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
7060 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
7061 \ CMP #4,TOS \ hardware RST
7062 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
7063 \ CMP #2,TOS \ Power_ON event
7064 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
7066 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
7068 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
7070 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
7071 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
7072 \ ------------------------------\
7073 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
7074 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7075 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7076 \ -- \ID input divider \ 10 = /4
7077 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7078 \ - \TBCLR TimerB Clear
7081 \ -------------------------------\
7082 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7083 \ -- \CM Capture Mode
7088 \ --- \OUTMOD \ 011 = set/reset
7094 \ -------------------------------\
7096 \ -------------------------------\
7098 \ ------------------------------\
7099 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7100 \ ------------------------------\
7101 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7102 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7103 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
7104 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7106 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
7107 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
7109 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
7110 \ ------------------------------\
7111 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
7112 \ ------------------------------\
7113 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
7114 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
7115 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7116 \ ------------------------------\
7117 BIS.B #LCDVo,&LCDVo_DIR \
7118 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
7119 \ ------------------------------\
7120 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7121 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7122 \ ------------------------------\
7123 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7124 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7125 \ ******************************\
7127 \ ******************************\
7128 BIS.B #RC5,&IR_IE \ enable RC5_Int
7129 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7130 \ ******************************\
7131 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
7132 \ ******************************\
7133 \ %01 0001 0100 \ TAxCTL
7134 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
7135 \ -- \ ID divided by 1
7136 \ -- \ MC MODE = up to TAxCCRn
7137 \ - \ TACLR clear timer count
7140 \ ------------------------------\
7141 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
7142 \ ------------------------------\
7144 \ --- \ TAIDEX pre divisor
7145 \ ------------------------------\
7146 \ %0000 0000 0000 0101 \ TAxCCR0
7147 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
7148 \ ------------------------------\
7149 \ %0000 0000 0001 0000 \ TAxCCTL0
7150 \ - \ CAP capture/compare mode = compare
7153 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
7154 \ ------------------------------\
7155 \ define LPM mode for ACCEPT \
7156 \ ------------------------------\
7157 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
7158 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7159 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7160 \ ------------------------------\
7162 \ ------------------------------\
7164 \ ------------------------------\
7165 #1000 20_US \ 1- wait 20 ms
7166 %011 TOP_LCD \ 2- send DB5=DB4=1
7167 #205 20_US \ 3- wait 4,1 ms
7168 %011 TOP_LCD \ 4- send again DB5=DB4=1
7169 #5 20_US \ 5- wait 0,1 ms
7170 %011 TOP_LCD \ 6- send again again DB5=DB4=1
7171 #2 20_US \ wait 40 us = LCD cycle
7172 %010 TOP_LCD \ 7- send DB5=1 DB4=0
7173 #2 20_US \ wait 40 us = LCD cycle
7174 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7175 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7176 LCD_CLEAR \ 10- "LCD_Clear"
7177 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7178 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7179 LCD_CLEAR \ 10- "LCD_Clear"
7180 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7181 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7182 CR ." I love you" \ display message on LCD
7183 ['] CR >BODY IS CR \ CR executes its default value
7184 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
7185 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7188 \ ------------------------------\
7190 \ ------------------------------\
7191 CODE START \ this routine replaces WARM and COLD default values by these of this application.
7192 \ ------------------------------\
7193 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
7194 0= IF \ if not done, customizes MARKER_DOES
7195 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
7196 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
7197 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
7198 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
7199 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
7200 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
7201 MOV #RC5_INT,&IR_VEC \ init interrupt vector
7202 MOV #INI_R2L,PC \ then execute new INI_APP, without return
7206 \ ------------------------------\
7209 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
7211 MARKER {RC5TOLCD} \ restore the state before MARKER definition
7212 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
7213 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
7214 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
7215 \ {RC5TOLCD}+14: make room to save previous IR_VEC
7217 [UNDEFINED] CONSTANT [IF]
7218 \ https://forth-standard.org/standard/core/CONSTANT
7219 \ CONSTANT <name> n -- define a Forth CONSTANT
7223 MOV TOS,-2(W) \ PFA = n
7230 [UNDEFINED] STATE [IF]
7231 \ https://forth-standard.org/standard/core/STATE
7232 \ STATE -- a-addr holds compiler state
7233 STATEADR CONSTANT STATE
7237 \ https://forth-standard.org/standard/core/Equal
7238 \ = x1 x2 -- flag test x1=x2
7245 XOR #-1,TOS \ 1 flag Z = 1
7250 [UNDEFINED] IF [IF] \ define IF and THEN
7251 \ https://forth-standard.org/standard/core/IF
7252 \ IF -- IFadr initialize conditional forward branch
7256 MOV &DP,TOS \ -- HERE
7257 ADD #4,&DP \ compile one word, reserve one word
7258 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
7259 ADD #2,TOS \ -- HERE+2=IFadr
7263 \ https://forth-standard.org/standard/core/THEN
7264 \ THEN IFadr -- resolve forward branch
7265 CODE THEN \ immediate
7266 MOV &DP,0(TOS) \ -- IFadr
7272 [UNDEFINED] ELSE [IF]
7273 \ https://forth-standard.org/standard/core/ELSE
7274 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
7275 CODE ELSE \ immediate
7276 ADD #4,&DP \ make room to compile two words
7277 MOV &DP,W \ W=HERE+4
7279 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
7281 MOV W,TOS \ -- ELSEadr
7286 [UNDEFINED] IS [IF] \ define DEFER! and IS
7288 \ https://forth-standard.org/standard/core/DEFERStore
7289 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
7290 CODE DEFER! \ xt2 xt1 --
7291 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
7296 \ https://forth-standard.org/standard/core/IS
7299 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
7300 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
7301 \ or in a definition : ... ['] U. IS DISPLAY ...
7302 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
7304 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
7308 IF POSTPONE ['] POSTPONE DEFER!
7314 [UNDEFINED] >BODY [IF]
7315 \ https://forth-standard.org/standard/core/toBODY
7316 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
7323 \ CODE 20uS \ n -- 8MHz version
7324 \ BEGIN \ 4 + 16 ~ loop
7325 \ MOV #39,rDOCON \ 39
7332 \ MOV #XDOCON,rDOCON \ 2
7337 CODE 20_US \ n -- n * 20 us
7338 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7340 BIT #1,&LCD_TIM_CTL \ 3
7341 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7342 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7344 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7349 CODE TOP_LCD \ LCD Sample
7350 \ \ if write : %xxxx_WWWW --
7351 \ \ if read : -- %0000_RRRR
7352 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7353 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7354 0= IF \ write LCD bits pattern
7356 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7357 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7360 THEN \ read LCD bits pattern
7363 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7364 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7369 CODE LCD_WRC \ char -- Write Char
7370 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7372 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
7373 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
7374 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7375 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7376 COLON \ high level word starts here
7377 TOP_LCD 2 20_US \ write high nibble first
7381 CODE LCD_WRF \ func -- Write Fonction
7382 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7386 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7387 : LCD_HOME $02 LCD_WRF 100 20_us ;
7389 \ [UNDEFINED] OR [IF]
7391 \ \ https://forth-standard.org/standard/core/OR
7392 \ \ C OR x1 x2 -- x3 logical OR
7400 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7401 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7402 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7403 \ : LCD_FN_SET $20 OR LCD_WrF ;
7404 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7405 \ : LCD_GOTO $80 OR LCD_WrF ;
7408 \ CODE LCD_RDS \ -- status Read Status
7409 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7410 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7411 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7412 \ COLON \ starts a FORTH word
7413 \ TOP_LCD 2 20_us \ -- %0000_HHHH
7414 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
7415 \ HI2LO \ switch from FORTH to assembler
7416 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
7417 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
7418 \ MOV @RSP+,IP \ restore IP saved by COLON
7422 \ CODE LCD_RDC \ -- char Read Char
7423 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7428 \ ******************************\
7429 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7430 \ ******************************\
7431 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7432 BIT.B #SW2,&SW2_IN \ test switch S2
7433 0= IF \ case of switch S2 pressed
7434 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7436 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7439 BIT.B #SW1,&SW1_IN \ test switch S1 input
7440 0= IF \ case of Switch S1 pressed
7441 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7443 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7450 \ ******************************\
7451 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
7452 \ ******************************\
7453 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7454 \ ******************************\
7455 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7456 \ \ SMclock = 8|16|24 MHz
7457 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7458 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7459 \ \ SR(9)=new Toggle bit memory (ADD on)
7460 \ ******************************\
7461 \ RC5_FirstStartBitHalfCycle: \
7462 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7463 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
7464 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
7466 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
7467 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
7469 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
7470 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
7472 MOV #1778,X \ RC5_Period * 1us
7473 MOV #14,W \ count of loop
7475 \ ******************************\
7476 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
7477 \ ******************************\ |
7478 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7479 \ RC5_Compute_3/4_Period: \ |
7480 RRUM #1,X \ X=1/2 cycle |
7483 ADD X,Y \ Y=3/4 cycle
7484 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
7486 \ ******************************\
7487 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7488 \ ******************************\
7489 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7490 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
7491 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7492 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7493 SUB #1,W \ decrement count loop
7494 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
7495 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7496 0<> WHILE \ ----> out of loop ----+
7497 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7499 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
7500 CMP Y,X \ 1 | cycle time out of bound ?
7502 BIC #$30,&RC5_TIM_CTL \ | | stop timer
7503 GOTO FW1 \ | | quit on truncated RC5 message
7505 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
7507 REPEAT \ ----> loop back --+ | with X = new RC5_period value
7508 \ ******************************\ |
7509 \ RC5_SampleEndOf: \ <---------------------+
7510 \ ******************************\
7511 BIC #$30,&RC5_TIM_CTL \ stop timer
7512 \ ******************************\
7513 \ RC5_ComputeNewRC5word \
7514 \ ******************************\
7515 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
7516 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
7517 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
7518 \ ******************************\
7519 \ RC5_ComputeC6bit \
7520 \ ******************************\
7521 BIT #BIT14,T \ test /C6 bit in T
7522 0= IF BIS #BIT6,X \ set C6 bit in X
7523 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
7524 \ ******************************\
7525 \ RC5_CommandByteIsDone \ -- BASE RC5_code
7526 \ ******************************\
7527 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
7528 \ ******************************\
7529 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
7530 XOR @RSP,T \ (new XOR old) Toggle bits
7531 BIT #UF10,T \ repeated RC5_command ?
7532 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
7533 XOR #UF10,0(RSP) \ 5 toggle bit memory
7534 \ ******************************\
7535 \ Display IR_RC5 code \
7536 \ ******************************\
7537 SUB #8,PSP \ TOS -- x x x x TOS
7538 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
7539 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
7540 MOV #$10,&BASEADR \ set hexadecimal base
7541 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
7542 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
7543 LO2HI \ switch from assembler to FORTH
7544 LCD_CLEAR \ set LCD cursor at home
7545 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
7546 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
7547 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
7548 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
7549 HI2LO \ -- switch from FORTH to assembler
7550 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
7551 MOV @PSP+,TOS \ -- TOS
7553 MOV @RSP+,SR \ restore SR flags
7554 BIC #%1111_1000,SR \ but force CPU Active Mode
7555 RET \ (instead of RETI)
7559 \ ------------------------------\
7560 HDNCODE STOP_R2L \ define new STOP_APP
7561 \ ------------------------------\
7562 CMP #RET_ADR,&{RC5TOLCD}+8 \
7563 0<> IF \ if previous START executing
7564 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
7565 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
7566 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
7567 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
7568 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
7569 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
7570 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
7571 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
7572 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
7573 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
7578 \ ------------------------------\
7580 \ ------------------------------\
7581 BW1 \ <-- INI_R2L for some events
7583 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
7585 ." RC5toLCD is removed,"
7586 ." type START to restart"
7589 \ ------------------------------\
7591 \ ------------------------------\
7592 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
7593 \ ------------------------------\
7595 \ ------------------------------\
7596 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
7597 \ ------------------------------\
7598 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
7599 \ ------------------------------\
7600 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
7601 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
7603 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
7604 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
7606 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
7607 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
7608 \ CMP #4,TOS \ hardware RST
7609 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
7610 \ CMP #2,TOS \ Power_ON event
7611 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
7613 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
7615 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
7617 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
7618 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
7619 \ ------------------------------\
7620 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
7621 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7622 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7623 \ -- \ID input divider \ 10 = /4
7624 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7625 \ - \TBCLR TimerB Clear
7628 \ -------------------------------\
7629 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7630 \ -- \CM Capture Mode
7635 \ --- \OUTMOD \ 011 = set/reset
7641 \ -------------------------------\
7643 \ -------------------------------\
7645 \ ------------------------------\
7646 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7647 \ ------------------------------\
7648 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7649 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7650 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
7651 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7653 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
7654 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
7656 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
7657 \ ------------------------------\
7658 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
7659 \ ------------------------------\
7660 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
7661 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
7662 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7663 \ ------------------------------\
7664 BIS.B #LCDVo,&LCDVo_DIR \
7665 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
7666 \ ------------------------------\
7667 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7668 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7669 \ ------------------------------\
7670 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7671 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7672 \ ******************************\
7674 \ ******************************\
7675 BIS.B #RC5,&IR_IE \ enable RC5_Int
7676 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7677 \ ******************************\
7678 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
7679 \ ******************************\
7680 \ %01 0001 0100 \ TAxCTL
7681 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
7682 \ -- \ ID divided by 1
7683 \ -- \ MC MODE = up to TAxCCRn
7684 \ - \ TACLR clear timer count
7687 \ ------------------------------\
7688 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
7689 \ ------------------------------\
7691 \ --- \ TAIDEX pre divisor
7692 \ ------------------------------\
7693 \ %0000 0000 0000 0101 \ TAxCCR0
7694 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
7695 \ ------------------------------\
7696 \ %0000 0000 0001 0000 \ TAxCCTL0
7697 \ - \ CAP capture/compare mode = compare
7700 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
7701 \ ------------------------------\
7702 \ define LPM mode for ACCEPT \
7703 \ ------------------------------\
7704 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
7705 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7706 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7707 \ ------------------------------\
7709 \ ------------------------------\
7711 \ ------------------------------\
7712 #1000 20_US \ 1- wait 20 ms
7713 %011 TOP_LCD \ 2- send DB5=DB4=1
7714 #205 20_US \ 3- wait 4,1 ms
7715 %011 TOP_LCD \ 4- send again DB5=DB4=1
7716 #5 20_US \ 5- wait 0,1 ms
7717 %011 TOP_LCD \ 6- send again again DB5=DB4=1
7718 #2 20_US \ wait 40 us = LCD cycle
7719 %010 TOP_LCD \ 7- send DB5=1 DB4=0
7720 #2 20_US \ wait 40 us = LCD cycle
7721 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7722 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7723 LCD_CLEAR \ 10- "LCD_Clear"
7724 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7725 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7726 LCD_CLEAR \ 10- "LCD_Clear"
7727 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7728 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7729 CR ." I love you" \ display message on LCD
7730 ['] CR >BODY IS CR \ CR executes its default value
7731 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
7732 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7735 \ ------------------------------\
7737 \ ------------------------------\
7738 CODE START \ this routine replaces WARM and COLD default values by these of this application.
7739 \ ------------------------------\
7740 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
7741 0= IF \ if not done, customizes MARKER_DOES
7742 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
7743 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
7744 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
7745 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
7746 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
7747 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
7748 MOV #RC5_INT,&IR_VEC \ init interrupt vector
7749 MOV #INI_R2L,PC \ then execute new INI_APP, without return
7753 \ ------------------------------\
7756 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
7758 MARKER {RC5TOLCD} \ restore the state before MARKER definition
7759 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
7760 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
7761 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
7762 \ {RC5TOLCD}+14: make room to save previous IR_VEC
7764 [UNDEFINED] CONSTANT [IF]
7765 \ https://forth-standard.org/standard/core/CONSTANT
7766 \ CONSTANT <name> n -- define a Forth CONSTANT
7770 MOV TOS,-2(W) \ PFA = n
7777 [UNDEFINED] STATE [IF]
7778 \ https://forth-standard.org/standard/core/STATE
7779 \ STATE -- a-addr holds compiler state
7780 STATEADR CONSTANT STATE
7784 \ https://forth-standard.org/standard/core/Equal
7785 \ = x1 x2 -- flag test x1=x2
7792 XOR #-1,TOS \ 1 flag Z = 1
7797 [UNDEFINED] IF [IF] \ define IF and THEN
7798 \ https://forth-standard.org/standard/core/IF
7799 \ IF -- IFadr initialize conditional forward branch
7803 MOV &DP,TOS \ -- HERE
7804 ADD #4,&DP \ compile one word, reserve one word
7805 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
7806 ADD #2,TOS \ -- HERE+2=IFadr
7810 \ https://forth-standard.org/standard/core/THEN
7811 \ THEN IFadr -- resolve forward branch
7812 CODE THEN \ immediate
7813 MOV &DP,0(TOS) \ -- IFadr
7819 [UNDEFINED] ELSE [IF]
7820 \ https://forth-standard.org/standard/core/ELSE
7821 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
7822 CODE ELSE \ immediate
7823 ADD #4,&DP \ make room to compile two words
7824 MOV &DP,W \ W=HERE+4
7826 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
7828 MOV W,TOS \ -- ELSEadr
7833 [UNDEFINED] IS [IF] \ define DEFER! and IS
7835 \ https://forth-standard.org/standard/core/DEFERStore
7836 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
7837 CODE DEFER! \ xt2 xt1 --
7838 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
7843 \ https://forth-standard.org/standard/core/IS
7846 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
7847 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
7848 \ or in a definition : ... ['] U. IS DISPLAY ...
7849 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
7851 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
7855 IF POSTPONE ['] POSTPONE DEFER!
7861 [UNDEFINED] >BODY [IF]
7862 \ https://forth-standard.org/standard/core/toBODY
7863 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
7870 \ CODE 20uS \ n -- 8MHz version
7871 \ BEGIN \ 4 + 16 ~ loop
7872 \ MOV #39,rDOCON \ 39
7879 \ MOV #XDOCON,rDOCON \ 2
7884 CODE 20_US \ n -- n * 20 us
7885 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7887 BIT #1,&LCD_TIM_CTL \ 3
7888 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7889 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7891 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7896 CODE TOP_LCD \ LCD Sample
7897 \ \ if write : %xxxx_WWWW --
7898 \ \ if read : -- %0000_RRRR
7899 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7900 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7901 0= IF \ write LCD bits pattern
7903 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7904 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7907 THEN \ read LCD bits pattern
7910 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7911 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7916 CODE LCD_WRC \ char -- Write Char
7917 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7919 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
7920 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
7921 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7922 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7923 COLON \ high level word starts here
7924 TOP_LCD 2 20_US \ write high nibble first
7928 CODE LCD_WRF \ func -- Write Fonction
7929 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7933 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7934 : LCD_HOME $02 LCD_WRF 100 20_us ;
7936 \ [UNDEFINED] OR [IF]
7938 \ \ https://forth-standard.org/standard/core/OR
7939 \ \ C OR x1 x2 -- x3 logical OR
7947 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7948 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7949 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7950 \ : LCD_FN_SET $20 OR LCD_WrF ;
7951 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7952 \ : LCD_GOTO $80 OR LCD_WrF ;
7955 \ CODE LCD_RDS \ -- status Read Status
7956 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7957 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7958 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7959 \ COLON \ starts a FORTH word
7960 \ TOP_LCD 2 20_us \ -- %0000_HHHH
7961 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
7962 \ HI2LO \ switch from FORTH to assembler
7963 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
7964 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
7965 \ MOV @RSP+,IP \ restore IP saved by COLON
7969 \ CODE LCD_RDC \ -- char Read Char
7970 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7975 \ ******************************\
7976 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7977 \ ******************************\
7978 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7979 BIT.B #SW2,&SW2_IN \ test switch S2
7980 0= IF \ case of switch S2 pressed
7981 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7983 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7986 BIT.B #SW1,&SW1_IN \ test switch S1 input
7987 0= IF \ case of Switch S1 pressed
7988 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7990 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7997 \ ******************************\
7998 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
7999 \ ******************************\
8000 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8001 \ ******************************\
8002 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8003 \ \ SMclock = 8|16|24 MHz
8004 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
8005 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
8006 \ \ SR(9)=new Toggle bit memory (ADD on)
8007 \ ******************************\
8008 \ RC5_FirstStartBitHalfCycle: \
8009 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
8010 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
8011 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
8013 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
8014 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
8016 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
8017 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
8019 MOV #1778,X \ RC5_Period * 1us
8020 MOV #14,W \ count of loop
8022 \ ******************************\
8023 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
8024 \ ******************************\ |
8025 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
8026 \ RC5_Compute_3/4_Period: \ |
8027 RRUM #1,X \ X=1/2 cycle |
8030 ADD X,Y \ Y=3/4 cycle
8031 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
8033 \ ******************************\
8034 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
8035 \ ******************************\
8036 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8037 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
8038 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8039 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8040 SUB #1,W \ decrement count loop
8041 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
8042 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8043 0<> WHILE \ ----> out of loop ----+
8044 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8046 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
8047 CMP Y,X \ 1 | cycle time out of bound ?
8049 BIC #$30,&RC5_TIM_CTL \ | | stop timer
8050 GOTO FW1 \ | | quit on truncated RC5 message
8052 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
8054 REPEAT \ ----> loop back --+ | with X = new RC5_period value
8055 \ ******************************\ |
8056 \ RC5_SampleEndOf: \ <---------------------+
8057 \ ******************************\
8058 BIC #$30,&RC5_TIM_CTL \ stop timer
8059 \ ******************************\
8060 \ RC5_ComputeNewRC5word \
8061 \ ******************************\
8062 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
8063 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
8064 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
8065 \ ******************************\
8066 \ RC5_ComputeC6bit \
8067 \ ******************************\
8068 BIT #BIT14,T \ test /C6 bit in T
8069 0= IF BIS #BIT6,X \ set C6 bit in X
8070 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
8071 \ ******************************\
8072 \ RC5_CommandByteIsDone \ -- BASE RC5_code
8073 \ ******************************\
8074 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
8075 \ ******************************\
8076 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
8077 XOR @RSP,T \ (new XOR old) Toggle bits
8078 BIT #UF10,T \ repeated RC5_command ?
8079 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
8080 XOR #UF10,0(RSP) \ 5 toggle bit memory
8081 \ ******************************\
8082 \ Display IR_RC5 code \
8083 \ ******************************\
8084 SUB #8,PSP \ TOS -- x x x x TOS
8085 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
8086 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
8087 MOV #$10,&BASEADR \ set hexadecimal base
8088 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
8089 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
8090 LO2HI \ switch from assembler to FORTH
8091 LCD_CLEAR \ set LCD cursor at home
8092 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
8093 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
8094 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
8095 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
8096 HI2LO \ -- switch from FORTH to assembler
8097 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
8098 MOV @PSP+,TOS \ -- TOS
8100 MOV @RSP+,SR \ restore SR flags
8101 BIC #%1111_1000,SR \ but force CPU Active Mode
8102 RET \ (instead of RETI)
8106 \ ------------------------------\
8107 HDNCODE STOP_R2L \ define new STOP_APP
8108 \ ------------------------------\
8109 CMP #RET_ADR,&{RC5TOLCD}+8 \
8110 0<> IF \ if previous START executing
8111 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
8112 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
8113 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
8114 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
8115 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
8116 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
8117 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
8118 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
8119 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
8120 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
8125 \ ------------------------------\
8127 \ ------------------------------\
8128 BW1 \ <-- INI_R2L for some events
8130 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
8132 ." RC5toLCD is removed,"
8133 ." type START to restart"
8136 \ ------------------------------\
8138 \ ------------------------------\
8139 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
8140 \ ------------------------------\
8142 \ ------------------------------\
8143 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
8144 \ ------------------------------\
8145 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
8146 \ ------------------------------\
8147 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
8148 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
8150 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
8151 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
8153 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
8154 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
8155 \ CMP #4,TOS \ hardware RST
8156 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
8157 \ CMP #2,TOS \ Power_ON event
8158 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
8160 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
8162 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
8164 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
8165 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
8166 \ ------------------------------\
8167 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
8168 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8169 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8170 \ -- \ID input divider \ 10 = /4
8171 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8172 \ - \TBCLR TimerB Clear
8175 \ -------------------------------\
8176 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8177 \ -- \CM Capture Mode
8182 \ --- \OUTMOD \ 011 = set/reset
8188 \ -------------------------------\
8190 \ -------------------------------\
8192 \ ------------------------------\
8193 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8194 \ ------------------------------\
8195 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8196 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8197 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
8198 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8200 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
8201 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8203 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8204 \ ------------------------------\
8205 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8206 \ ------------------------------\
8207 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8208 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8209 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8210 \ ------------------------------\
8211 BIS.B #LCDVo,&LCDVo_DIR \
8212 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8213 \ ------------------------------\
8214 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8215 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8216 \ ------------------------------\
8217 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8218 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8219 \ ******************************\
8221 \ ******************************\
8222 BIS.B #RC5,&IR_IE \ enable RC5_Int
8223 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8224 \ ******************************\
8225 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8226 \ ******************************\
8227 \ %01 0001 0100 \ TAxCTL
8228 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8229 \ -- \ ID divided by 1
8230 \ -- \ MC MODE = up to TAxCCRn
8231 \ - \ TACLR clear timer count
8234 \ ------------------------------\
8235 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8236 \ ------------------------------\
8238 \ --- \ TAIDEX pre divisor
8239 \ ------------------------------\
8240 \ %0000 0000 0000 0101 \ TAxCCR0
8241 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8242 \ ------------------------------\
8243 \ %0000 0000 0001 0000 \ TAxCCTL0
8244 \ - \ CAP capture/compare mode = compare
8247 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8248 \ ------------------------------\
8249 \ define LPM mode for ACCEPT \
8250 \ ------------------------------\
8251 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
8252 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8253 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8254 \ ------------------------------\
8256 \ ------------------------------\
8258 \ ------------------------------\
8259 #1000 20_US \ 1- wait 20 ms
8260 %011 TOP_LCD \ 2- send DB5=DB4=1
8261 #205 20_US \ 3- wait 4,1 ms
8262 %011 TOP_LCD \ 4- send again DB5=DB4=1
8263 #5 20_US \ 5- wait 0,1 ms
8264 %011 TOP_LCD \ 6- send again again DB5=DB4=1
8265 #2 20_US \ wait 40 us = LCD cycle
8266 %010 TOP_LCD \ 7- send DB5=1 DB4=0
8267 #2 20_US \ wait 40 us = LCD cycle
8268 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8269 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8270 LCD_CLEAR \ 10- "LCD_Clear"
8271 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8272 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8273 LCD_CLEAR \ 10- "LCD_Clear"
8274 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8275 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8276 CR ." I love you" \ display message on LCD
8277 ['] CR >BODY IS CR \ CR executes its default value
8278 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
8279 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8282 \ ------------------------------\
8284 \ ------------------------------\
8285 CODE START \ this routine replaces WARM and COLD default values by these of this application.
8286 \ ------------------------------\
8287 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
8288 0= IF \ if not done, customizes MARKER_DOES
8289 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
8290 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
8291 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
8292 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
8293 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8294 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
8295 MOV #RC5_INT,&IR_VEC \ init interrupt vector
8296 MOV #INI_R2L,PC \ then execute new INI_APP, without return
8300 \ ------------------------------\
8303 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
8305 MARKER {RC5TOLCD} \ restore the state before MARKER definition
8306 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
8307 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
8308 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
8309 \ {RC5TOLCD}+14: make room to save previous IR_VEC
8311 [UNDEFINED] CONSTANT [IF]
8312 \ https://forth-standard.org/standard/core/CONSTANT
8313 \ CONSTANT <name> n -- define a Forth CONSTANT
8317 MOV TOS,-2(W) \ PFA = n
8324 [UNDEFINED] STATE [IF]
8325 \ https://forth-standard.org/standard/core/STATE
8326 \ STATE -- a-addr holds compiler state
8327 STATEADR CONSTANT STATE
8331 \ https://forth-standard.org/standard/core/Equal
8332 \ = x1 x2 -- flag test x1=x2
8339 XOR #-1,TOS \ 1 flag Z = 1
8344 [UNDEFINED] IF [IF] \ define IF and THEN
8345 \ https://forth-standard.org/standard/core/IF
8346 \ IF -- IFadr initialize conditional forward branch
8350 MOV &DP,TOS \ -- HERE
8351 ADD #4,&DP \ compile one word, reserve one word
8352 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
8353 ADD #2,TOS \ -- HERE+2=IFadr
8357 \ https://forth-standard.org/standard/core/THEN
8358 \ THEN IFadr -- resolve forward branch
8359 CODE THEN \ immediate
8360 MOV &DP,0(TOS) \ -- IFadr
8366 [UNDEFINED] ELSE [IF]
8367 \ https://forth-standard.org/standard/core/ELSE
8368 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
8369 CODE ELSE \ immediate
8370 ADD #4,&DP \ make room to compile two words
8371 MOV &DP,W \ W=HERE+4
8373 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
8375 MOV W,TOS \ -- ELSEadr
8380 [UNDEFINED] IS [IF] \ define DEFER! and IS
8382 \ https://forth-standard.org/standard/core/DEFERStore
8383 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
8384 CODE DEFER! \ xt2 xt1 --
8385 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
8390 \ https://forth-standard.org/standard/core/IS
8393 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
8394 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
8395 \ or in a definition : ... ['] U. IS DISPLAY ...
8396 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
8398 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
8402 IF POSTPONE ['] POSTPONE DEFER!
8408 [UNDEFINED] >BODY [IF]
8409 \ https://forth-standard.org/standard/core/toBODY
8410 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
8417 \ CODE 20uS \ n -- 8MHz version
8418 \ BEGIN \ 4 + 16 ~ loop
8419 \ MOV #39,rDOCON \ 39
8426 \ MOV #XDOCON,rDOCON \ 2
8431 CODE 20_US \ n -- n * 20 us
8432 BEGIN \ here we presume that LCD_TIM_IFG = 1...
8434 BIT #1,&LCD_TIM_CTL \ 3
8435 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
8436 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
8438 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
8443 CODE TOP_LCD \ LCD Sample
8444 \ \ if write : %xxxx_WWWW --
8445 \ \ if read : -- %0000_RRRR
8446 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8447 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8448 0= IF \ write LCD bits pattern
8450 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8451 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8454 THEN \ read LCD bits pattern
8457 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8458 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8463 CODE LCD_WRC \ char -- Write Char
8464 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8466 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
8467 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
8468 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8469 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8470 COLON \ high level word starts here
8471 TOP_LCD 2 20_US \ write high nibble first
8475 CODE LCD_WRF \ func -- Write Fonction
8476 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8480 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
8481 : LCD_HOME $02 LCD_WRF 100 20_us ;
8483 \ [UNDEFINED] OR [IF]
8485 \ \ https://forth-standard.org/standard/core/OR
8486 \ \ C OR x1 x2 -- x3 logical OR
8494 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
8495 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
8496 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
8497 \ : LCD_FN_SET $20 OR LCD_WrF ;
8498 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
8499 \ : LCD_GOTO $80 OR LCD_WrF ;
8502 \ CODE LCD_RDS \ -- status Read Status
8503 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8504 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8505 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8506 \ COLON \ starts a FORTH word
8507 \ TOP_LCD 2 20_us \ -- %0000_HHHH
8508 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
8509 \ HI2LO \ switch from FORTH to assembler
8510 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
8511 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
8512 \ MOV @RSP+,IP \ restore IP saved by COLON
8516 \ CODE LCD_RDC \ -- char Read Char
8517 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8522 \ ******************************\
8523 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8524 \ ******************************\
8525 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
8526 BIT.B #SW2,&SW2_IN \ test switch S2
8527 0= IF \ case of switch S2 pressed
8528 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
8530 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
8533 BIT.B #SW1,&SW1_IN \ test switch S1 input
8534 0= IF \ case of Switch S1 pressed
8535 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
8537 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
8544 \ ******************************\
8545 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
8546 \ ******************************\
8547 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8548 \ ******************************\
8549 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8550 \ \ SMclock = 8|16|24 MHz
8551 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
8552 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
8553 \ \ SR(9)=new Toggle bit memory (ADD on)
8554 \ ******************************\
8555 \ RC5_FirstStartBitHalfCycle: \
8556 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
8557 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
8558 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
8560 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
8561 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
8563 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
8564 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
8566 MOV #1778,X \ RC5_Period * 1us
8567 MOV #14,W \ count of loop
8569 \ ******************************\
8570 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
8571 \ ******************************\ |
8572 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
8573 \ RC5_Compute_3/4_Period: \ |
8574 RRUM #1,X \ X=1/2 cycle |
8577 ADD X,Y \ Y=3/4 cycle
8578 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
8580 \ ******************************\
8581 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
8582 \ ******************************\
8583 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8584 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
8585 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8586 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8587 SUB #1,W \ decrement count loop
8588 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
8589 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8590 0<> WHILE \ ----> out of loop ----+
8591 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8593 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
8594 CMP Y,X \ 1 | cycle time out of bound ?
8596 BIC #$30,&RC5_TIM_CTL \ | | stop timer
8597 GOTO FW1 \ | | quit on truncated RC5 message
8599 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
8601 REPEAT \ ----> loop back --+ | with X = new RC5_period value
8602 \ ******************************\ |
8603 \ RC5_SampleEndOf: \ <---------------------+
8604 \ ******************************\
8605 BIC #$30,&RC5_TIM_CTL \ stop timer
8606 \ ******************************\
8607 \ RC5_ComputeNewRC5word \
8608 \ ******************************\
8609 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
8610 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
8611 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
8612 \ ******************************\
8613 \ RC5_ComputeC6bit \
8614 \ ******************************\
8615 BIT #BIT14,T \ test /C6 bit in T
8616 0= IF BIS #BIT6,X \ set C6 bit in X
8617 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
8618 \ ******************************\
8619 \ RC5_CommandByteIsDone \ -- BASE RC5_code
8620 \ ******************************\
8621 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
8622 \ ******************************\
8623 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
8624 XOR @RSP,T \ (new XOR old) Toggle bits
8625 BIT #UF10,T \ repeated RC5_command ?
8626 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
8627 XOR #UF10,0(RSP) \ 5 toggle bit memory
8628 \ ******************************\
8629 \ Display IR_RC5 code \
8630 \ ******************************\
8631 SUB #8,PSP \ TOS -- x x x x TOS
8632 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
8633 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
8634 MOV #$10,&BASEADR \ set hexadecimal base
8635 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
8636 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
8637 LO2HI \ switch from assembler to FORTH
8638 LCD_CLEAR \ set LCD cursor at home
8639 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
8640 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
8641 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
8642 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
8643 HI2LO \ -- switch from FORTH to assembler
8644 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
8645 MOV @PSP+,TOS \ -- TOS
8647 MOV @RSP+,SR \ restore SR flags
8648 BIC #%1111_1000,SR \ but force CPU Active Mode
8649 RET \ (instead of RETI)
8653 \ ------------------------------\
8654 HDNCODE STOP_R2L \ define new STOP_APP
8655 \ ------------------------------\
8656 CMP #RET_ADR,&{RC5TOLCD}+8 \
8657 0<> IF \ if previous START executing
8658 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
8659 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
8660 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
8661 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
8662 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
8663 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
8664 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
8665 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
8666 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
8667 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
8672 \ ------------------------------\
8674 \ ------------------------------\
8675 BW1 \ <-- INI_R2L for some events
8677 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
8679 ." RC5toLCD is removed,"
8680 ." type START to restart"
8683 \ ------------------------------\
8685 \ ------------------------------\
8686 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
8687 \ ------------------------------\
8689 \ ------------------------------\
8690 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
8691 \ ------------------------------\
8692 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
8693 \ ------------------------------\
8694 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
8695 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
8697 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
8698 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
8700 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
8701 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
8702 \ CMP #4,TOS \ hardware RST
8703 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
8704 \ CMP #2,TOS \ Power_ON event
8705 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
8707 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
8709 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
8711 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
8712 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
8713 \ ------------------------------\
8714 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
8715 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8716 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8717 \ -- \ID input divider \ 10 = /4
8718 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8719 \ - \TBCLR TimerB Clear
8722 \ -------------------------------\
8723 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8724 \ -- \CM Capture Mode
8729 \ --- \OUTMOD \ 011 = set/reset
8735 \ -------------------------------\
8737 \ -------------------------------\
8739 \ ------------------------------\
8740 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8741 \ ------------------------------\
8742 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8743 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8744 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
8745 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8747 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
8748 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8750 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8751 \ ------------------------------\
8752 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8753 \ ------------------------------\
8754 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8755 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8756 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8757 \ ------------------------------\
8758 BIS.B #LCDVo,&LCDVo_DIR \
8759 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8760 \ ------------------------------\
8761 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8762 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8763 \ ------------------------------\
8764 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8765 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8766 \ ******************************\
8768 \ ******************************\
8769 BIS.B #RC5,&IR_IE \ enable RC5_Int
8770 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8771 \ ******************************\
8772 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8773 \ ******************************\
8774 \ %01 0001 0100 \ TAxCTL
8775 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8776 \ -- \ ID divided by 1
8777 \ -- \ MC MODE = up to TAxCCRn
8778 \ - \ TACLR clear timer count
8781 \ ------------------------------\
8782 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8783 \ ------------------------------\
8785 \ --- \ TAIDEX pre divisor
8786 \ ------------------------------\
8787 \ %0000 0000 0000 0101 \ TAxCCR0
8788 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8789 \ ------------------------------\
8790 \ %0000 0000 0001 0000 \ TAxCCTL0
8791 \ - \ CAP capture/compare mode = compare
8794 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8795 \ ------------------------------\
8796 \ define LPM mode for ACCEPT \
8797 \ ------------------------------\
8798 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
8799 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8800 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8801 \ ------------------------------\
8803 \ ------------------------------\
8805 \ ------------------------------\
8806 #1000 20_US \ 1- wait 20 ms
8807 %011 TOP_LCD \ 2- send DB5=DB4=1
8808 #205 20_US \ 3- wait 4,1 ms
8809 %011 TOP_LCD \ 4- send again DB5=DB4=1
8810 #5 20_US \ 5- wait 0,1 ms
8811 %011 TOP_LCD \ 6- send again again DB5=DB4=1
8812 #2 20_US \ wait 40 us = LCD cycle
8813 %010 TOP_LCD \ 7- send DB5=1 DB4=0
8814 #2 20_US \ wait 40 us = LCD cycle
8815 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8816 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8817 LCD_CLEAR \ 10- "LCD_Clear"
8818 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8819 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8820 LCD_CLEAR \ 10- "LCD_Clear"
8821 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8822 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8823 CR ." I love you" \ display message on LCD
8824 ['] CR >BODY IS CR \ CR executes its default value
8825 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
8826 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8829 \ ------------------------------\
8831 \ ------------------------------\
8832 CODE START \ this routine replaces WARM and COLD default values by these of this application.
8833 \ ------------------------------\
8834 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
8835 0= IF \ if not done, customizes MARKER_DOES
8836 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
8837 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
8838 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
8839 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
8840 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8841 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
8842 MOV #RC5_INT,&IR_VEC \ init interrupt vector
8843 MOV #INI_R2L,PC \ then execute new INI_APP, without return
8847 \ ------------------------------\
8850 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
8852 MARKER {RC5TOLCD} \ restore the state before MARKER definition
8853 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
8854 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
8855 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
8856 \ {RC5TOLCD}+14: make room to save previous IR_VEC
8858 [UNDEFINED] CONSTANT [IF]
8859 \ https://forth-standard.org/standard/core/CONSTANT
8860 \ CONSTANT <name> n -- define a Forth CONSTANT
8864 MOV TOS,-2(W) \ PFA = n
8871 [UNDEFINED] STATE [IF]
8872 \ https://forth-standard.org/standard/core/STATE
8873 \ STATE -- a-addr holds compiler state
8874 STATEADR CONSTANT STATE
8878 \ https://forth-standard.org/standard/core/Equal
8879 \ = x1 x2 -- flag test x1=x2
8886 XOR #-1,TOS \ 1 flag Z = 1
8891 [UNDEFINED] IF [IF] \ define IF and THEN
8892 \ https://forth-standard.org/standard/core/IF
8893 \ IF -- IFadr initialize conditional forward branch
8897 MOV &DP,TOS \ -- HERE
8898 ADD #4,&DP \ compile one word, reserve one word
8899 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
8900 ADD #2,TOS \ -- HERE+2=IFadr
8904 \ https://forth-standard.org/standard/core/THEN
8905 \ THEN IFadr -- resolve forward branch
8906 CODE THEN \ immediate
8907 MOV &DP,0(TOS) \ -- IFadr
8913 [UNDEFINED] ELSE [IF]
8914 \ https://forth-standard.org/standard/core/ELSE
8915 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
8916 CODE ELSE \ immediate
8917 ADD #4,&DP \ make room to compile two words
8918 MOV &DP,W \ W=HERE+4
8920 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
8922 MOV W,TOS \ -- ELSEadr
8927 [UNDEFINED] IS [IF] \ define DEFER! and IS
8929 \ https://forth-standard.org/standard/core/DEFERStore
8930 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
8931 CODE DEFER! \ xt2 xt1 --
8932 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
8937 \ https://forth-standard.org/standard/core/IS
8940 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
8941 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
8942 \ or in a definition : ... ['] U. IS DISPLAY ...
8943 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
8945 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
8949 IF POSTPONE ['] POSTPONE DEFER!
8955 [UNDEFINED] >BODY [IF]
8956 \ https://forth-standard.org/standard/core/toBODY
8957 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
8964 \ CODE 20uS \ n -- 8MHz version
8965 \ BEGIN \ 4 + 16 ~ loop
8966 \ MOV #39,rDOCON \ 39
8973 \ MOV #XDOCON,rDOCON \ 2
8978 CODE 20_US \ n -- n * 20 us
8979 BEGIN \ here we presume that LCD_TIM_IFG = 1...
8981 BIT #1,&LCD_TIM_CTL \ 3
8982 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
8983 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
8985 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
8990 CODE TOP_LCD \ LCD Sample
8991 \ \ if write : %xxxx_WWWW --
8992 \ \ if read : -- %0000_RRRR
8993 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8994 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8995 0= IF \ write LCD bits pattern
8997 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8998 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9001 THEN \ read LCD bits pattern
9004 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9005 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9010 CODE LCD_WRC \ char -- Write Char
9011 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9013 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
9014 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
9015 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9016 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9017 COLON \ high level word starts here
9018 TOP_LCD 2 20_US \ write high nibble first
9022 CODE LCD_WRF \ func -- Write Fonction
9023 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9027 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
9028 : LCD_HOME $02 LCD_WRF 100 20_us ;
9030 \ [UNDEFINED] OR [IF]
9032 \ \ https://forth-standard.org/standard/core/OR
9033 \ \ C OR x1 x2 -- x3 logical OR
9041 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
9042 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
9043 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
9044 \ : LCD_FN_SET $20 OR LCD_WrF ;
9045 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
9046 \ : LCD_GOTO $80 OR LCD_WrF ;
9049 \ CODE LCD_RDS \ -- status Read Status
9050 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9051 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9052 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9053 \ COLON \ starts a FORTH word
9054 \ TOP_LCD 2 20_us \ -- %0000_HHHH
9055 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
9056 \ HI2LO \ switch from FORTH to assembler
9057 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
9058 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
9059 \ MOV @RSP+,IP \ restore IP saved by COLON
9063 \ CODE LCD_RDC \ -- char Read Char
9064 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9069 \ ******************************\
9070 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9071 \ ******************************\
9072 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9073 BIT.B #SW2,&SW2_IN \ test switch S2
9074 0= IF \ case of switch S2 pressed
9075 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9077 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9080 BIT.B #SW1,&SW1_IN \ test switch S1 input
9081 0= IF \ case of Switch S1 pressed
9082 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9084 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9091 \ ******************************\
9092 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
9093 \ ******************************\
9094 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9095 \ ******************************\
9096 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9097 \ \ SMclock = 8|16|24 MHz
9098 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9099 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9100 \ \ SR(9)=new Toggle bit memory (ADD on)
9101 \ ******************************\
9102 \ RC5_FirstStartBitHalfCycle: \
9103 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9104 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
9105 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
9107 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
9108 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
9110 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
9111 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
9113 MOV #1778,X \ RC5_Period * 1us
9114 MOV #14,W \ count of loop
9116 \ ******************************\
9117 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
9118 \ ******************************\ |
9119 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9120 \ RC5_Compute_3/4_Period: \ |
9121 RRUM #1,X \ X=1/2 cycle |
9124 ADD X,Y \ Y=3/4 cycle
9125 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
9127 \ ******************************\
9128 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9129 \ ******************************\
9130 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9131 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
9132 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9133 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9134 SUB #1,W \ decrement count loop
9135 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
9136 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9137 0<> WHILE \ ----> out of loop ----+
9138 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9140 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
9141 CMP Y,X \ 1 | cycle time out of bound ?
9143 BIC #$30,&RC5_TIM_CTL \ | | stop timer
9144 GOTO FW1 \ | | quit on truncated RC5 message
9146 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
9148 REPEAT \ ----> loop back --+ | with X = new RC5_period value
9149 \ ******************************\ |
9150 \ RC5_SampleEndOf: \ <---------------------+
9151 \ ******************************\
9152 BIC #$30,&RC5_TIM_CTL \ stop timer
9153 \ ******************************\
9154 \ RC5_ComputeNewRC5word \
9155 \ ******************************\
9156 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
9157 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
9158 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
9159 \ ******************************\
9160 \ RC5_ComputeC6bit \
9161 \ ******************************\
9162 BIT #BIT14,T \ test /C6 bit in T
9163 0= IF BIS #BIT6,X \ set C6 bit in X
9164 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
9165 \ ******************************\
9166 \ RC5_CommandByteIsDone \ -- BASE RC5_code
9167 \ ******************************\
9168 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
9169 \ ******************************\
9170 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
9171 XOR @RSP,T \ (new XOR old) Toggle bits
9172 BIT #UF10,T \ repeated RC5_command ?
9173 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
9174 XOR #UF10,0(RSP) \ 5 toggle bit memory
9175 \ ******************************\
9176 \ Display IR_RC5 code \
9177 \ ******************************\
9178 SUB #8,PSP \ TOS -- x x x x TOS
9179 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
9180 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
9181 MOV #$10,&BASEADR \ set hexadecimal base
9182 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
9183 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
9184 LO2HI \ switch from assembler to FORTH
9185 LCD_CLEAR \ set LCD cursor at home
9186 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
9187 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
9188 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
9189 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
9190 HI2LO \ -- switch from FORTH to assembler
9191 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
9192 MOV @PSP+,TOS \ -- TOS
9194 MOV @RSP+,SR \ restore SR flags
9195 BIC #%1111_1000,SR \ but force CPU Active Mode
9196 RET \ (instead of RETI)
9200 \ ------------------------------\
9201 HDNCODE STOP_R2L \ define new STOP_APP
9202 \ ------------------------------\
9203 CMP #RET_ADR,&{RC5TOLCD}+8 \
9204 0<> IF \ if previous START executing
9205 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
9206 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
9207 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
9208 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
9209 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
9210 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
9211 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
9212 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
9213 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
9214 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
9219 \ ------------------------------\
9221 \ ------------------------------\
9222 BW1 \ <-- INI_R2L for some events
9224 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
9226 ." RC5toLCD is removed,"
9227 ." type START to restart"
9230 \ ------------------------------\
9232 \ ------------------------------\
9233 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
9234 \ ------------------------------\
9236 \ ------------------------------\
9237 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
9238 \ ------------------------------\
9239 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
9240 \ ------------------------------\
9241 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
9242 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
9244 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
9245 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
9247 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
9248 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
9249 \ CMP #4,TOS \ hardware RST
9250 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
9251 \ CMP #2,TOS \ Power_ON event
9252 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9254 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9256 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9258 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9259 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
9260 \ ------------------------------\
9261 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
9262 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9263 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9264 \ -- \ID input divider \ 10 = /4
9265 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9266 \ - \TBCLR TimerB Clear
9269 \ -------------------------------\
9270 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9271 \ -- \CM Capture Mode
9276 \ --- \OUTMOD \ 011 = set/reset
9282 \ -------------------------------\
9284 \ -------------------------------\
9286 \ ------------------------------\
9287 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9288 \ ------------------------------\
9289 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9290 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9291 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
9292 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9294 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
9295 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9297 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
9298 \ ------------------------------\
9299 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9300 \ ------------------------------\
9301 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
9302 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9303 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9304 \ ------------------------------\
9305 BIS.B #LCDVo,&LCDVo_DIR \
9306 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
9307 \ ------------------------------\
9308 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9309 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9310 \ ------------------------------\
9311 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9312 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9313 \ ******************************\
9315 \ ******************************\
9316 BIS.B #RC5,&IR_IE \ enable RC5_Int
9317 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9318 \ ******************************\
9319 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9320 \ ******************************\
9321 \ %01 0001 0100 \ TAxCTL
9322 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
9323 \ -- \ ID divided by 1
9324 \ -- \ MC MODE = up to TAxCCRn
9325 \ - \ TACLR clear timer count
9328 \ ------------------------------\
9329 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
9330 \ ------------------------------\
9332 \ --- \ TAIDEX pre divisor
9333 \ ------------------------------\
9334 \ %0000 0000 0000 0101 \ TAxCCR0
9335 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9336 \ ------------------------------\
9337 \ %0000 0000 0001 0000 \ TAxCCTL0
9338 \ - \ CAP capture/compare mode = compare
9341 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
9342 \ ------------------------------\
9343 \ define LPM mode for ACCEPT \
9344 \ ------------------------------\
9345 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
9346 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9347 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9348 \ ------------------------------\
9350 \ ------------------------------\
9352 \ ------------------------------\
9353 #1000 20_US \ 1- wait 20 ms
9354 %011 TOP_LCD \ 2- send DB5=DB4=1
9355 #205 20_US \ 3- wait 4,1 ms
9356 %011 TOP_LCD \ 4- send again DB5=DB4=1
9357 #5 20_US \ 5- wait 0,1 ms
9358 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9359 #2 20_US \ wait 40 us = LCD cycle
9360 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9361 #2 20_US \ wait 40 us = LCD cycle
9362 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9363 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9364 LCD_CLEAR \ 10- "LCD_Clear"
9365 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9366 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9367 LCD_CLEAR \ 10- "LCD_Clear"
9368 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9369 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9370 CR ." I love you" \ display message on LCD
9371 ['] CR >BODY IS CR \ CR executes its default value
9372 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9373 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9376 \ ------------------------------\
9378 \ ------------------------------\
9379 CODE START \ this routine replaces WARM and COLD default values by these of this application.
9380 \ ------------------------------\
9381 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
9382 0= IF \ if not done, customizes MARKER_DOES
9383 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
9384 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
9385 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
9386 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
9387 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9388 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
9389 MOV #RC5_INT,&IR_VEC \ init interrupt vector
9390 MOV #INI_R2L,PC \ then execute new INI_APP, without return
9394 \ ------------------------------\
9397 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9399 MARKER {RC5TOLCD} \ restore the state before MARKER definition
9400 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
9401 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
9402 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
9403 \ {RC5TOLCD}+14: make room to save previous IR_VEC
9405 [UNDEFINED] CONSTANT [IF]
9406 \ https://forth-standard.org/standard/core/CONSTANT
9407 \ CONSTANT <name> n -- define a Forth CONSTANT
9411 MOV TOS,-2(W) \ PFA = n
9418 [UNDEFINED] STATE [IF]
9419 \ https://forth-standard.org/standard/core/STATE
9420 \ STATE -- a-addr holds compiler state
9421 STATEADR CONSTANT STATE
9425 \ https://forth-standard.org/standard/core/Equal
9426 \ = x1 x2 -- flag test x1=x2
9433 XOR #-1,TOS \ 1 flag Z = 1
9438 [UNDEFINED] IF [IF] \ define IF and THEN
9439 \ https://forth-standard.org/standard/core/IF
9440 \ IF -- IFadr initialize conditional forward branch
9444 MOV &DP,TOS \ -- HERE
9445 ADD #4,&DP \ compile one word, reserve one word
9446 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
9447 ADD #2,TOS \ -- HERE+2=IFadr
9451 \ https://forth-standard.org/standard/core/THEN
9452 \ THEN IFadr -- resolve forward branch
9453 CODE THEN \ immediate
9454 MOV &DP,0(TOS) \ -- IFadr
9460 [UNDEFINED] ELSE [IF]
9461 \ https://forth-standard.org/standard/core/ELSE
9462 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
9463 CODE ELSE \ immediate
9464 ADD #4,&DP \ make room to compile two words
9465 MOV &DP,W \ W=HERE+4
9467 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
9469 MOV W,TOS \ -- ELSEadr
9474 [UNDEFINED] IS [IF] \ define DEFER! and IS
9476 \ https://forth-standard.org/standard/core/DEFERStore
9477 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
9478 CODE DEFER! \ xt2 xt1 --
9479 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
9484 \ https://forth-standard.org/standard/core/IS
9487 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
9488 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
9489 \ or in a definition : ... ['] U. IS DISPLAY ...
9490 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
9492 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
9496 IF POSTPONE ['] POSTPONE DEFER!
9502 [UNDEFINED] >BODY [IF]
9503 \ https://forth-standard.org/standard/core/toBODY
9504 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
9511 \ CODE 20uS \ n -- 8MHz version
9512 \ BEGIN \ 4 + 16 ~ loop
9513 \ MOV #39,rDOCON \ 39
9520 \ MOV #XDOCON,rDOCON \ 2
9525 CODE 20_US \ n -- n * 20 us
9526 BEGIN \ here we presume that LCD_TIM_IFG = 1...
9528 BIT #1,&LCD_TIM_CTL \ 3
9529 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
9530 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
9532 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
9537 CODE TOP_LCD \ LCD Sample
9538 \ \ if write : %xxxx_WWWW --
9539 \ \ if read : -- %0000_RRRR
9540 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9541 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9542 0= IF \ write LCD bits pattern
9544 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9545 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9548 THEN \ read LCD bits pattern
9551 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9552 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9557 CODE LCD_WRC \ char -- Write Char
9558 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9560 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
9561 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
9562 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9563 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9564 COLON \ high level word starts here
9565 TOP_LCD 2 20_US \ write high nibble first
9569 CODE LCD_WRF \ func -- Write Fonction
9570 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9574 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
9575 : LCD_HOME $02 LCD_WRF 100 20_us ;
9577 \ [UNDEFINED] OR [IF]
9579 \ \ https://forth-standard.org/standard/core/OR
9580 \ \ C OR x1 x2 -- x3 logical OR
9588 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
9589 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
9590 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
9591 \ : LCD_FN_SET $20 OR LCD_WrF ;
9592 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
9593 \ : LCD_GOTO $80 OR LCD_WrF ;
9596 \ CODE LCD_RDS \ -- status Read Status
9597 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9598 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9599 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9600 \ COLON \ starts a FORTH word
9601 \ TOP_LCD 2 20_us \ -- %0000_HHHH
9602 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
9603 \ HI2LO \ switch from FORTH to assembler
9604 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
9605 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
9606 \ MOV @RSP+,IP \ restore IP saved by COLON
9610 \ CODE LCD_RDC \ -- char Read Char
9611 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9616 \ ******************************\
9617 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9618 \ ******************************\
9619 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9620 BIT.B #SW2,&SW2_IN \ test switch S2
9621 0= IF \ case of switch S2 pressed
9622 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9624 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9627 BIT.B #SW1,&SW1_IN \ test switch S1 input
9628 0= IF \ case of Switch S1 pressed
9629 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9631 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9638 \ ******************************\
9639 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
9640 \ ******************************\
9641 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9642 \ ******************************\
9643 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9644 \ \ SMclock = 8|16|24 MHz
9645 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9646 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9647 \ \ SR(9)=new Toggle bit memory (ADD on)
9648 \ ******************************\
9649 \ RC5_FirstStartBitHalfCycle: \
9650 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9651 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
9652 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
9654 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
9655 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
9657 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
9658 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
9660 MOV #1778,X \ RC5_Period * 1us
9661 MOV #14,W \ count of loop
9663 \ ******************************\
9664 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
9665 \ ******************************\ |
9666 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9667 \ RC5_Compute_3/4_Period: \ |
9668 RRUM #1,X \ X=1/2 cycle |
9671 ADD X,Y \ Y=3/4 cycle
9672 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
9674 \ ******************************\
9675 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9676 \ ******************************\
9677 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9678 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
9679 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9680 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9681 SUB #1,W \ decrement count loop
9682 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
9683 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9684 0<> WHILE \ ----> out of loop ----+
9685 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9687 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
9688 CMP Y,X \ 1 | cycle time out of bound ?
9690 BIC #$30,&RC5_TIM_CTL \ | | stop timer
9691 GOTO FW1 \ | | quit on truncated RC5 message
9693 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
9695 REPEAT \ ----> loop back --+ | with X = new RC5_period value
9696 \ ******************************\ |
9697 \ RC5_SampleEndOf: \ <---------------------+
9698 \ ******************************\
9699 BIC #$30,&RC5_TIM_CTL \ stop timer
9700 \ ******************************\
9701 \ RC5_ComputeNewRC5word \
9702 \ ******************************\
9703 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
9704 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
9705 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
9706 \ ******************************\
9707 \ RC5_ComputeC6bit \
9708 \ ******************************\
9709 BIT #BIT14,T \ test /C6 bit in T
9710 0= IF BIS #BIT6,X \ set C6 bit in X
9711 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
9712 \ ******************************\
9713 \ RC5_CommandByteIsDone \ -- BASE RC5_code
9714 \ ******************************\
9715 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
9716 \ ******************************\
9717 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
9718 XOR @RSP,T \ (new XOR old) Toggle bits
9719 BIT #UF10,T \ repeated RC5_command ?
9720 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
9721 XOR #UF10,0(RSP) \ 5 toggle bit memory
9722 \ ******************************\
9723 \ Display IR_RC5 code \
9724 \ ******************************\
9725 SUB #8,PSP \ TOS -- x x x x TOS
9726 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
9727 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
9728 MOV #$10,&BASEADR \ set hexadecimal base
9729 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
9730 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
9731 LO2HI \ switch from assembler to FORTH
9732 LCD_CLEAR \ set LCD cursor at home
9733 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
9734 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
9735 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
9736 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
9737 HI2LO \ -- switch from FORTH to assembler
9738 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
9739 MOV @PSP+,TOS \ -- TOS
9741 MOV @RSP+,SR \ restore SR flags
9742 BIC #%1111_1000,SR \ but force CPU Active Mode
9743 RET \ (instead of RETI)
9747 \ ------------------------------\
9748 HDNCODE STOP_R2L \ define new STOP_APP
9749 \ ------------------------------\
9750 CMP #RET_ADR,&{RC5TOLCD}+8 \
9751 0<> IF \ if previous START executing
9752 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
9753 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
9754 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
9755 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
9756 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
9757 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
9758 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
9759 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
9760 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
9761 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
9766 \ ------------------------------\
9768 \ ------------------------------\
9769 BW1 \ <-- INI_R2L for some events
9771 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
9773 ." RC5toLCD is removed,"
9774 ." type START to restart"
9777 \ ------------------------------\
9779 \ ------------------------------\
9780 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
9781 \ ------------------------------\
9783 \ ------------------------------\
9784 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
9785 \ ------------------------------\
9786 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
9787 \ ------------------------------\
9788 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
9789 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
9791 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
9792 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
9794 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
9795 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
9796 \ CMP #4,TOS \ hardware RST
9797 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
9798 \ CMP #2,TOS \ Power_ON event
9799 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9801 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9803 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9805 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9806 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
9807 \ ------------------------------\
9808 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
9809 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9810 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9811 \ -- \ID input divider \ 10 = /4
9812 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9813 \ - \TBCLR TimerB Clear
9816 \ -------------------------------\
9817 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9818 \ -- \CM Capture Mode
9823 \ --- \OUTMOD \ 011 = set/reset
9829 \ -------------------------------\
9831 \ -------------------------------\
9833 \ ------------------------------\
9834 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9835 \ ------------------------------\
9836 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9837 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9838 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
9839 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9841 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
9842 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9844 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
9845 \ ------------------------------\
9846 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9847 \ ------------------------------\
9848 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
9849 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9850 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9851 \ ------------------------------\
9852 BIS.B #LCDVo,&LCDVo_DIR \
9853 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
9854 \ ------------------------------\
9855 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9856 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9857 \ ------------------------------\
9858 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9859 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9860 \ ******************************\
9862 \ ******************************\
9863 BIS.B #RC5,&IR_IE \ enable RC5_Int
9864 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9865 \ ******************************\
9866 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9867 \ ******************************\
9868 \ %01 0001 0100 \ TAxCTL
9869 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
9870 \ -- \ ID divided by 1
9871 \ -- \ MC MODE = up to TAxCCRn
9872 \ - \ TACLR clear timer count
9875 \ ------------------------------\
9876 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
9877 \ ------------------------------\
9879 \ --- \ TAIDEX pre divisor
9880 \ ------------------------------\
9881 \ %0000 0000 0000 0101 \ TAxCCR0
9882 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9883 \ ------------------------------\
9884 \ %0000 0000 0001 0000 \ TAxCCTL0
9885 \ - \ CAP capture/compare mode = compare
9888 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
9889 \ ------------------------------\
9890 \ define LPM mode for ACCEPT \
9891 \ ------------------------------\
9892 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
9893 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9894 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9895 \ ------------------------------\
9897 \ ------------------------------\
9899 \ ------------------------------\
9900 #1000 20_US \ 1- wait 20 ms
9901 %011 TOP_LCD \ 2- send DB5=DB4=1
9902 #205 20_US \ 3- wait 4,1 ms
9903 %011 TOP_LCD \ 4- send again DB5=DB4=1
9904 #5 20_US \ 5- wait 0,1 ms
9905 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9906 #2 20_US \ wait 40 us = LCD cycle
9907 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9908 #2 20_US \ wait 40 us = LCD cycle
9909 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9910 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9911 LCD_CLEAR \ 10- "LCD_Clear"
9912 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9913 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9914 LCD_CLEAR \ 10- "LCD_Clear"
9915 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9916 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9917 CR ." I love you" \ display message on LCD
9918 ['] CR >BODY IS CR \ CR executes its default value
9919 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9920 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9923 \ ------------------------------\
9925 \ ------------------------------\
9926 CODE START \ this routine replaces WARM and COLD default values by these of this application.
9927 \ ------------------------------\
9928 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
9929 0= IF \ if not done, customizes MARKER_DOES
9930 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
9931 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
9932 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
9933 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
9934 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9935 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
9936 MOV #RC5_INT,&IR_VEC \ init interrupt vector
9937 MOV #INI_R2L,PC \ then execute new INI_APP, without return
9941 \ ------------------------------\
9944 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9946 MARKER {RC5TOLCD} \ restore the state before MARKER definition
9947 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
9948 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
9949 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
9950 \ {RC5TOLCD}+14: make room to save previous IR_VEC
9952 [UNDEFINED] CONSTANT [IF]
9953 \ https://forth-standard.org/standard/core/CONSTANT
9954 \ CONSTANT <name> n -- define a Forth CONSTANT
9958 MOV TOS,-2(W) \ PFA = n
9965 [UNDEFINED] STATE [IF]
9966 \ https://forth-standard.org/standard/core/STATE
9967 \ STATE -- a-addr holds compiler state
9968 STATEADR CONSTANT STATE
9972 \ https://forth-standard.org/standard/core/Equal
9973 \ = x1 x2 -- flag test x1=x2
9980 XOR #-1,TOS \ 1 flag Z = 1
9985 [UNDEFINED] IF [IF] \ define IF and THEN
9986 \ https://forth-standard.org/standard/core/IF
9987 \ IF -- IFadr initialize conditional forward branch
9991 MOV &DP,TOS \ -- HERE
9992 ADD #4,&DP \ compile one word, reserve one word
9993 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
9994 ADD #2,TOS \ -- HERE+2=IFadr
9998 \ https://forth-standard.org/standard/core/THEN
9999 \ THEN IFadr -- resolve forward branch
10000 CODE THEN \ immediate
10001 MOV &DP,0(TOS) \ -- IFadr
10007 [UNDEFINED] ELSE [IF]
10008 \ https://forth-standard.org/standard/core/ELSE
10009 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
10010 CODE ELSE \ immediate
10011 ADD #4,&DP \ make room to compile two words
10012 MOV &DP,W \ W=HERE+4
10014 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
10016 MOV W,TOS \ -- ELSEadr
10021 [UNDEFINED] IS [IF] \ define DEFER! and IS
10023 \ https://forth-standard.org/standard/core/DEFERStore
10024 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
10025 CODE DEFER! \ xt2 xt1 --
10026 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
10031 \ https://forth-standard.org/standard/core/IS
10034 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
10035 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
10036 \ or in a definition : ... ['] U. IS DISPLAY ...
10037 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
10039 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
10043 IF POSTPONE ['] POSTPONE DEFER!
10049 [UNDEFINED] >BODY [IF]
10050 \ https://forth-standard.org/standard/core/toBODY
10051 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
10058 \ CODE 20uS \ n -- 8MHz version
10059 \ BEGIN \ 4 + 16 ~ loop
10060 \ MOV #39,rDOCON \ 39
10067 \ MOV #XDOCON,rDOCON \ 2
10072 CODE 20_US \ n -- n * 20 us
10073 BEGIN \ here we presume that LCD_TIM_IFG = 1...
10075 BIT #1,&LCD_TIM_CTL \ 3
10076 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
10077 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
10079 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
10084 CODE TOP_LCD \ LCD Sample
10085 \ \ if write : %xxxx_WWWW --
10086 \ \ if read : -- %0000_RRRR
10087 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10088 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10089 0= IF \ write LCD bits pattern
10090 AND.B #LCD_DB,TOS \
10091 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10092 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10095 THEN \ read LCD bits pattern
10098 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10099 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10100 AND.B #LCD_DB,TOS \
10104 CODE LCD_WRC \ char -- Write Char
10105 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10107 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
10108 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
10109 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10110 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10111 COLON \ high level word starts here
10112 TOP_LCD 2 20_US \ write high nibble first
10116 CODE LCD_WRF \ func -- Write Fonction
10117 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10121 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
10122 : LCD_HOME $02 LCD_WRF 100 20_us ;
10124 \ [UNDEFINED] OR [IF]
10126 \ \ https://forth-standard.org/standard/core/OR
10127 \ \ C OR x1 x2 -- x3 logical OR
10135 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
10136 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
10137 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
10138 \ : LCD_FN_SET $20 OR LCD_WrF ;
10139 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
10140 \ : LCD_GOTO $80 OR LCD_WrF ;
10143 \ CODE LCD_RDS \ -- status Read Status
10144 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10145 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10146 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10147 \ COLON \ starts a FORTH word
10148 \ TOP_LCD 2 20_us \ -- %0000_HHHH
10149 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
10150 \ HI2LO \ switch from FORTH to assembler
10151 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
10152 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
10153 \ MOV @RSP+,IP \ restore IP saved by COLON
10157 \ CODE LCD_RDC \ -- char Read Char
10158 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10163 \ ******************************\
10164 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10165 \ ******************************\
10166 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
10167 BIT.B #SW2,&SW2_IN \ test switch S2
10168 0= IF \ case of switch S2 pressed
10169 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10171 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
10174 BIT.B #SW1,&SW1_IN \ test switch S1 input
10175 0= IF \ case of Switch S1 pressed
10176 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10178 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10185 \ ******************************\
10186 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
10187 \ ******************************\
10188 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10189 \ ******************************\
10190 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10191 \ \ SMclock = 8|16|24 MHz
10192 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10193 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10194 \ \ SR(9)=new Toggle bit memory (ADD on)
10195 \ ******************************\
10196 \ RC5_FirstStartBitHalfCycle: \
10197 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10198 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10199 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10201 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10202 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10204 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10205 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10207 MOV #1778,X \ RC5_Period * 1us
10208 MOV #14,W \ count of loop
10210 \ ******************************\
10211 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10212 \ ******************************\ |
10213 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10214 \ RC5_Compute_3/4_Period: \ |
10215 RRUM #1,X \ X=1/2 cycle |
10218 ADD X,Y \ Y=3/4 cycle
10219 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10221 \ ******************************\
10222 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10223 \ ******************************\
10224 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10225 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10226 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10227 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10228 SUB #1,W \ decrement count loop
10229 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10230 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10231 0<> WHILE \ ----> out of loop ----+
10232 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10234 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10235 CMP Y,X \ 1 | cycle time out of bound ?
10236 U>= IF \ 2 ^ | yes:
10237 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10238 GOTO FW1 \ | | quit on truncated RC5 message
10240 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10242 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10243 \ ******************************\ |
10244 \ RC5_SampleEndOf: \ <---------------------+
10245 \ ******************************\
10246 BIC #$30,&RC5_TIM_CTL \ stop timer
10247 \ ******************************\
10248 \ RC5_ComputeNewRC5word \
10249 \ ******************************\
10250 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10251 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10252 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10253 \ ******************************\
10254 \ RC5_ComputeC6bit \
10255 \ ******************************\
10256 BIT #BIT14,T \ test /C6 bit in T
10257 0= IF BIS #BIT6,X \ set C6 bit in X
10258 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10259 \ ******************************\
10260 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10261 \ ******************************\
10262 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
10263 \ ******************************\
10264 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10265 XOR @RSP,T \ (new XOR old) Toggle bits
10266 BIT #UF10,T \ repeated RC5_command ?
10267 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
10268 XOR #UF10,0(RSP) \ 5 toggle bit memory
10269 \ ******************************\
10270 \ Display IR_RC5 code \
10271 \ ******************************\
10272 SUB #8,PSP \ TOS -- x x x x TOS
10273 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10274 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10275 MOV #$10,&BASEADR \ set hexadecimal base
10276 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10277 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10278 LO2HI \ switch from assembler to FORTH
10279 LCD_CLEAR \ set LCD cursor at home
10280 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10281 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10282 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10283 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10284 HI2LO \ -- switch from FORTH to assembler
10285 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10286 MOV @PSP+,TOS \ -- TOS
10288 MOV @RSP+,SR \ restore SR flags
10289 BIC #%1111_1000,SR \ but force CPU Active Mode
10290 RET \ (instead of RETI)
10294 \ ------------------------------\
10295 HDNCODE STOP_R2L \ define new STOP_APP
10296 \ ------------------------------\
10297 CMP #RET_ADR,&{RC5TOLCD}+8 \
10298 0<> IF \ if previous START executing
10299 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
10300 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
10301 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
10302 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
10303 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
10304 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
10305 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
10306 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
10307 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
10308 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
10313 \ ------------------------------\
10315 \ ------------------------------\
10316 BW1 \ <-- INI_R2L for some events
10318 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
10320 ." RC5toLCD is removed,"
10321 ." type START to restart"
10324 \ ------------------------------\
10326 \ ------------------------------\
10327 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
10328 \ ------------------------------\
10330 \ ------------------------------\
10331 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
10332 \ ------------------------------\
10333 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
10334 \ ------------------------------\
10335 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
10336 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
10338 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
10339 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
10341 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
10342 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
10343 \ CMP #4,TOS \ hardware RST
10344 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
10345 \ CMP #2,TOS \ Power_ON event
10346 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
10348 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
10350 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
10352 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
10353 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
10354 \ ------------------------------\
10355 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
10356 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10357 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10358 \ -- \ID input divider \ 10 = /4
10359 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10360 \ - \TBCLR TimerB Clear
10363 \ -------------------------------\
10364 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10365 \ -- \CM Capture Mode
10370 \ --- \OUTMOD \ 011 = set/reset
10376 \ -------------------------------\
10378 \ -------------------------------\
10380 \ ------------------------------\
10381 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10382 \ ------------------------------\
10383 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10384 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10385 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
10386 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10388 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
10389 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10391 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
10392 \ ------------------------------\
10393 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10394 \ ------------------------------\
10395 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
10396 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10397 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10398 \ ------------------------------\
10399 BIS.B #LCDVo,&LCDVo_DIR \
10400 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
10401 \ ------------------------------\
10402 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10403 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10404 \ ------------------------------\
10405 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10406 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10407 \ ******************************\
10409 \ ******************************\
10410 BIS.B #RC5,&IR_IE \ enable RC5_Int
10411 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10412 \ ******************************\
10413 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
10414 \ ******************************\
10415 \ %01 0001 0100 \ TAxCTL
10416 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
10417 \ -- \ ID divided by 1
10418 \ -- \ MC MODE = up to TAxCCRn
10419 \ - \ TACLR clear timer count
10422 \ ------------------------------\
10423 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
10424 \ ------------------------------\
10426 \ --- \ TAIDEX pre divisor
10427 \ ------------------------------\
10428 \ %0000 0000 0000 0101 \ TAxCCR0
10429 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
10430 \ ------------------------------\
10431 \ %0000 0000 0001 0000 \ TAxCCTL0
10432 \ - \ CAP capture/compare mode = compare
10435 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
10436 \ ------------------------------\
10437 \ define LPM mode for ACCEPT \
10438 \ ------------------------------\
10439 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
10440 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10441 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10442 \ ------------------------------\
10444 \ ------------------------------\
10446 \ ------------------------------\
10447 #1000 20_US \ 1- wait 20 ms
10448 %011 TOP_LCD \ 2- send DB5=DB4=1
10449 #205 20_US \ 3- wait 4,1 ms
10450 %011 TOP_LCD \ 4- send again DB5=DB4=1
10451 #5 20_US \ 5- wait 0,1 ms
10452 %011 TOP_LCD \ 6- send again again DB5=DB4=1
10453 #2 20_US \ wait 40 us = LCD cycle
10454 %010 TOP_LCD \ 7- send DB5=1 DB4=0
10455 #2 20_US \ wait 40 us = LCD cycle
10456 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10457 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10458 LCD_CLEAR \ 10- "LCD_Clear"
10459 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10460 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10461 LCD_CLEAR \ 10- "LCD_Clear"
10462 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10463 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10464 CR ." I love you" \ display message on LCD
10465 ['] CR >BODY IS CR \ CR executes its default value
10466 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
10467 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
10470 \ ------------------------------\
10472 \ ------------------------------\
10473 CODE START \ this routine replaces WARM and COLD default values by these of this application.
10474 \ ------------------------------\
10475 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
10476 0= IF \ if not done, customizes MARKER_DOES
10477 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
10478 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
10479 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
10480 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
10481 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
10482 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
10483 MOV #RC5_INT,&IR_VEC \ init interrupt vector
10484 MOV #INI_R2L,PC \ then execute new INI_APP, without return
10488 \ ------------------------------\
10491 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
10493 MARKER {RC5TOLCD} \ restore the state before MARKER definition
10494 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
10495 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
10496 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
10497 \ {RC5TOLCD}+14: make room to save previous IR_VEC
10499 [UNDEFINED] CONSTANT [IF]
10500 \ https://forth-standard.org/standard/core/CONSTANT
10501 \ CONSTANT <name> n -- define a Forth CONSTANT
10505 MOV TOS,-2(W) \ PFA = n
10512 [UNDEFINED] STATE [IF]
10513 \ https://forth-standard.org/standard/core/STATE
10514 \ STATE -- a-addr holds compiler state
10515 STATEADR CONSTANT STATE
10519 \ https://forth-standard.org/standard/core/Equal
10520 \ = x1 x2 -- flag test x1=x2
10527 XOR #-1,TOS \ 1 flag Z = 1
10532 [UNDEFINED] IF [IF] \ define IF and THEN
10533 \ https://forth-standard.org/standard/core/IF
10534 \ IF -- IFadr initialize conditional forward branch
10535 CODE IF \ immediate
10538 MOV &DP,TOS \ -- HERE
10539 ADD #4,&DP \ compile one word, reserve one word
10540 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
10541 ADD #2,TOS \ -- HERE+2=IFadr
10545 \ https://forth-standard.org/standard/core/THEN
10546 \ THEN IFadr -- resolve forward branch
10547 CODE THEN \ immediate
10548 MOV &DP,0(TOS) \ -- IFadr
10554 [UNDEFINED] ELSE [IF]
10555 \ https://forth-standard.org/standard/core/ELSE
10556 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
10557 CODE ELSE \ immediate
10558 ADD #4,&DP \ make room to compile two words
10559 MOV &DP,W \ W=HERE+4
10561 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
10563 MOV W,TOS \ -- ELSEadr
10568 [UNDEFINED] IS [IF] \ define DEFER! and IS
10570 \ https://forth-standard.org/standard/core/DEFERStore
10571 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
10572 CODE DEFER! \ xt2 xt1 --
10573 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
10578 \ https://forth-standard.org/standard/core/IS
10581 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
10582 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
10583 \ or in a definition : ... ['] U. IS DISPLAY ...
10584 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
10586 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
10590 IF POSTPONE ['] POSTPONE DEFER!
10596 [UNDEFINED] >BODY [IF]
10597 \ https://forth-standard.org/standard/core/toBODY
10598 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
10605 \ CODE 20uS \ n -- 8MHz version
10606 \ BEGIN \ 4 + 16 ~ loop
10607 \ MOV #39,rDOCON \ 39
10614 \ MOV #XDOCON,rDOCON \ 2
10619 CODE 20_US \ n -- n * 20 us
10620 BEGIN \ here we presume that LCD_TIM_IFG = 1...
10622 BIT #1,&LCD_TIM_CTL \ 3
10623 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
10624 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
10626 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
10631 CODE TOP_LCD \ LCD Sample
10632 \ \ if write : %xxxx_WWWW --
10633 \ \ if read : -- %0000_RRRR
10634 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10635 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10636 0= IF \ write LCD bits pattern
10637 AND.B #LCD_DB,TOS \
10638 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10639 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10642 THEN \ read LCD bits pattern
10645 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10646 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10647 AND.B #LCD_DB,TOS \
10651 CODE LCD_WRC \ char -- Write Char
10652 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10654 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
10655 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
10656 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10657 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10658 COLON \ high level word starts here
10659 TOP_LCD 2 20_US \ write high nibble first
10663 CODE LCD_WRF \ func -- Write Fonction
10664 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10668 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
10669 : LCD_HOME $02 LCD_WRF 100 20_us ;
10671 \ [UNDEFINED] OR [IF]
10673 \ \ https://forth-standard.org/standard/core/OR
10674 \ \ C OR x1 x2 -- x3 logical OR
10682 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
10683 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
10684 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
10685 \ : LCD_FN_SET $20 OR LCD_WrF ;
10686 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
10687 \ : LCD_GOTO $80 OR LCD_WrF ;
10690 \ CODE LCD_RDS \ -- status Read Status
10691 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10692 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10693 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10694 \ COLON \ starts a FORTH word
10695 \ TOP_LCD 2 20_us \ -- %0000_HHHH
10696 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
10697 \ HI2LO \ switch from FORTH to assembler
10698 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
10699 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
10700 \ MOV @RSP+,IP \ restore IP saved by COLON
10704 \ CODE LCD_RDC \ -- char Read Char
10705 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10710 \ ******************************\
10711 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10712 \ ******************************\
10713 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
10714 BIT.B #SW2,&SW2_IN \ test switch S2
10715 0= IF \ case of switch S2 pressed
10716 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10718 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
10721 BIT.B #SW1,&SW1_IN \ test switch S1 input
10722 0= IF \ case of Switch S1 pressed
10723 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10725 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10732 \ ******************************\
10733 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
10734 \ ******************************\
10735 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10736 \ ******************************\
10737 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10738 \ \ SMclock = 8|16|24 MHz
10739 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10740 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10741 \ \ SR(9)=new Toggle bit memory (ADD on)
10742 \ ******************************\
10743 \ RC5_FirstStartBitHalfCycle: \
10744 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10745 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10746 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10748 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10749 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10751 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10752 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10754 MOV #1778,X \ RC5_Period * 1us
10755 MOV #14,W \ count of loop
10757 \ ******************************\
10758 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10759 \ ******************************\ |
10760 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10761 \ RC5_Compute_3/4_Period: \ |
10762 RRUM #1,X \ X=1/2 cycle |
10765 ADD X,Y \ Y=3/4 cycle
10766 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10768 \ ******************************\
10769 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10770 \ ******************************\
10771 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10772 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10773 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10774 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10775 SUB #1,W \ decrement count loop
10776 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10777 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10778 0<> WHILE \ ----> out of loop ----+
10779 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10781 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10782 CMP Y,X \ 1 | cycle time out of bound ?
10783 U>= IF \ 2 ^ | yes:
10784 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10785 GOTO FW1 \ | | quit on truncated RC5 message
10787 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10789 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10790 \ ******************************\ |
10791 \ RC5_SampleEndOf: \ <---------------------+
10792 \ ******************************\
10793 BIC #$30,&RC5_TIM_CTL \ stop timer
10794 \ ******************************\
10795 \ RC5_ComputeNewRC5word \
10796 \ ******************************\
10797 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10798 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10799 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10800 \ ******************************\
10801 \ RC5_ComputeC6bit \
10802 \ ******************************\
10803 BIT #BIT14,T \ test /C6 bit in T
10804 0= IF BIS #BIT6,X \ set C6 bit in X
10805 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10806 \ ******************************\
10807 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10808 \ ******************************\
10809 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
10810 \ ******************************\
10811 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10812 XOR @RSP,T \ (new XOR old) Toggle bits
10813 BIT #UF10,T \ repeated RC5_command ?
10814 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
10815 XOR #UF10,0(RSP) \ 5 toggle bit memory
10816 \ ******************************\
10817 \ Display IR_RC5 code \
10818 \ ******************************\
10819 SUB #8,PSP \ TOS -- x x x x TOS
10820 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10821 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10822 MOV #$10,&BASEADR \ set hexadecimal base
10823 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10824 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10825 LO2HI \ switch from assembler to FORTH
10826 LCD_CLEAR \ set LCD cursor at home
10827 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10828 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10829 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10830 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10831 HI2LO \ -- switch from FORTH to assembler
10832 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10833 MOV @PSP+,TOS \ -- TOS
10835 MOV @RSP+,SR \ restore SR flags
10836 BIC #%1111_1000,SR \ but force CPU Active Mode
10837 RET \ (instead of RETI)
10841 \ ------------------------------\
10842 HDNCODE STOP_R2L \ define new STOP_APP
10843 \ ------------------------------\
10844 CMP #RET_ADR,&{RC5TOLCD}+8 \
10845 0<> IF \ if previous START executing
10846 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
10847 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
10848 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
10849 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
10850 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
10851 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
10852 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
10853 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
10854 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
10855 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
10860 \ ------------------------------\
10862 \ ------------------------------\
10863 BW1 \ <-- INI_R2L for some events
10865 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
10867 ." RC5toLCD is removed,"
10868 ." type START to restart"
10871 \ ------------------------------\
10873 \ ------------------------------\
10874 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
10875 \ ------------------------------\
10877 \ ------------------------------\
10878 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
10879 \ ------------------------------\
10880 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
10881 \ ------------------------------\
10882 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
10883 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
10885 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
10886 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
10888 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
10889 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
10890 \ CMP #4,TOS \ hardware RST
10891 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
10892 \ CMP #2,TOS \ Power_ON event
10893 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
10895 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
10897 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
10899 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
10900 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
10901 \ ------------------------------\
10902 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
10903 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10904 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10905 \ -- \ID input divider \ 10 = /4
10906 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10907 \ - \TBCLR TimerB Clear
10910 \ -------------------------------\
10911 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10912 \ -- \CM Capture Mode
10917 \ --- \OUTMOD \ 011 = set/reset
10923 \ -------------------------------\
10925 \ -------------------------------\
10927 \ ------------------------------\
10928 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10929 \ ------------------------------\
10930 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10931 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10932 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
10933 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10935 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
10936 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10938 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
10939 \ ------------------------------\
10940 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10941 \ ------------------------------\
10942 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
10943 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10944 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10945 \ ------------------------------\
10946 BIS.B #LCDVo,&LCDVo_DIR \
10947 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
10948 \ ------------------------------\
10949 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10950 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10951 \ ------------------------------\
10952 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10953 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10954 \ ******************************\
10956 \ ******************************\
10957 BIS.B #RC5,&IR_IE \ enable RC5_Int
10958 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10959 \ ******************************\
10960 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
10961 \ ******************************\
10962 \ %01 0001 0100 \ TAxCTL
10963 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
10964 \ -- \ ID divided by 1
10965 \ -- \ MC MODE = up to TAxCCRn
10966 \ - \ TACLR clear timer count
10969 \ ------------------------------\
10970 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
10971 \ ------------------------------\
10973 \ --- \ TAIDEX pre divisor
10974 \ ------------------------------\
10975 \ %0000 0000 0000 0101 \ TAxCCR0
10976 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
10977 \ ------------------------------\
10978 \ %0000 0000 0001 0000 \ TAxCCTL0
10979 \ - \ CAP capture/compare mode = compare
10982 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
10983 \ ------------------------------\
10984 \ define LPM mode for ACCEPT \
10985 \ ------------------------------\
10986 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
10987 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10988 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10989 \ ------------------------------\
10991 \ ------------------------------\
10993 \ ------------------------------\
10994 #1000 20_US \ 1- wait 20 ms
10995 %011 TOP_LCD \ 2- send DB5=DB4=1
10996 #205 20_US \ 3- wait 4,1 ms
10997 %011 TOP_LCD \ 4- send again DB5=DB4=1
10998 #5 20_US \ 5- wait 0,1 ms
10999 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11000 #2 20_US \ wait 40 us = LCD cycle
11001 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11002 #2 20_US \ wait 40 us = LCD cycle
11003 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11004 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11005 LCD_CLEAR \ 10- "LCD_Clear"
11006 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11007 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11008 LCD_CLEAR \ 10- "LCD_Clear"
11009 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11010 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11011 CR ." I love you" \ display message on LCD
11012 ['] CR >BODY IS CR \ CR executes its default value
11013 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11014 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11017 \ ------------------------------\
11019 \ ------------------------------\
11020 CODE START \ this routine replaces WARM and COLD default values by these of this application.
11021 \ ------------------------------\
11022 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
11023 0= IF \ if not done, customizes MARKER_DOES
11024 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
11025 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
11026 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
11027 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
11028 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11029 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
11030 MOV #RC5_INT,&IR_VEC \ init interrupt vector
11031 MOV #INI_R2L,PC \ then execute new INI_APP, without return
11035 \ ------------------------------\
11038 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11040 MARKER {RC5TOLCD} \ restore the state before MARKER definition
11041 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
11042 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
11043 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
11044 \ {RC5TOLCD}+14: make room to save previous IR_VEC
11046 [UNDEFINED] CONSTANT [IF]
11047 \ https://forth-standard.org/standard/core/CONSTANT
11048 \ CONSTANT <name> n -- define a Forth CONSTANT
11052 MOV TOS,-2(W) \ PFA = n
11059 [UNDEFINED] STATE [IF]
11060 \ https://forth-standard.org/standard/core/STATE
11061 \ STATE -- a-addr holds compiler state
11062 STATEADR CONSTANT STATE
11066 \ https://forth-standard.org/standard/core/Equal
11067 \ = x1 x2 -- flag test x1=x2
11074 XOR #-1,TOS \ 1 flag Z = 1
11079 [UNDEFINED] IF [IF] \ define IF and THEN
11080 \ https://forth-standard.org/standard/core/IF
11081 \ IF -- IFadr initialize conditional forward branch
11082 CODE IF \ immediate
11085 MOV &DP,TOS \ -- HERE
11086 ADD #4,&DP \ compile one word, reserve one word
11087 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
11088 ADD #2,TOS \ -- HERE+2=IFadr
11092 \ https://forth-standard.org/standard/core/THEN
11093 \ THEN IFadr -- resolve forward branch
11094 CODE THEN \ immediate
11095 MOV &DP,0(TOS) \ -- IFadr
11101 [UNDEFINED] ELSE [IF]
11102 \ https://forth-standard.org/standard/core/ELSE
11103 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
11104 CODE ELSE \ immediate
11105 ADD #4,&DP \ make room to compile two words
11106 MOV &DP,W \ W=HERE+4
11108 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
11110 MOV W,TOS \ -- ELSEadr
11115 [UNDEFINED] IS [IF] \ define DEFER! and IS
11117 \ https://forth-standard.org/standard/core/DEFERStore
11118 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
11119 CODE DEFER! \ xt2 xt1 --
11120 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
11125 \ https://forth-standard.org/standard/core/IS
11128 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
11129 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
11130 \ or in a definition : ... ['] U. IS DISPLAY ...
11131 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
11133 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
11137 IF POSTPONE ['] POSTPONE DEFER!
11143 [UNDEFINED] >BODY [IF]
11144 \ https://forth-standard.org/standard/core/toBODY
11145 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
11152 \ CODE 20uS \ n -- 8MHz version
11153 \ BEGIN \ 4 + 16 ~ loop
11154 \ MOV #39,rDOCON \ 39
11161 \ MOV #XDOCON,rDOCON \ 2
11166 CODE 20_US \ n -- n * 20 us
11167 BEGIN \ here we presume that LCD_TIM_IFG = 1...
11169 BIT #1,&LCD_TIM_CTL \ 3
11170 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
11171 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
11173 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
11178 CODE TOP_LCD \ LCD Sample
11179 \ \ if write : %xxxx_WWWW --
11180 \ \ if read : -- %0000_RRRR
11181 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11182 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11183 0= IF \ write LCD bits pattern
11184 AND.B #LCD_DB,TOS \
11185 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11186 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11189 THEN \ read LCD bits pattern
11192 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11193 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11194 AND.B #LCD_DB,TOS \
11198 CODE LCD_WRC \ char -- Write Char
11199 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11201 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
11202 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
11203 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11204 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11205 COLON \ high level word starts here
11206 TOP_LCD 2 20_US \ write high nibble first
11210 CODE LCD_WRF \ func -- Write Fonction
11211 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11215 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
11216 : LCD_HOME $02 LCD_WRF 100 20_us ;
11218 \ [UNDEFINED] OR [IF]
11220 \ \ https://forth-standard.org/standard/core/OR
11221 \ \ C OR x1 x2 -- x3 logical OR
11229 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
11230 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
11231 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
11232 \ : LCD_FN_SET $20 OR LCD_WrF ;
11233 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
11234 \ : LCD_GOTO $80 OR LCD_WrF ;
11237 \ CODE LCD_RDS \ -- status Read Status
11238 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11239 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11240 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11241 \ COLON \ starts a FORTH word
11242 \ TOP_LCD 2 20_us \ -- %0000_HHHH
11243 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
11244 \ HI2LO \ switch from FORTH to assembler
11245 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
11246 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
11247 \ MOV @RSP+,IP \ restore IP saved by COLON
11251 \ CODE LCD_RDC \ -- char Read Char
11252 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11257 \ ******************************\
11258 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11259 \ ******************************\
11260 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
11261 BIT.B #SW2,&SW2_IN \ test switch S2
11262 0= IF \ case of switch S2 pressed
11263 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
11265 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
11268 BIT.B #SW1,&SW1_IN \ test switch S1 input
11269 0= IF \ case of Switch S1 pressed
11270 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
11272 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
11279 \ ******************************\
11280 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
11281 \ ******************************\
11282 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11283 \ ******************************\
11284 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11285 \ \ SMclock = 8|16|24 MHz
11286 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
11287 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
11288 \ \ SR(9)=new Toggle bit memory (ADD on)
11289 \ ******************************\
11290 \ RC5_FirstStartBitHalfCycle: \
11291 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
11292 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
11293 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
11295 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
11296 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
11298 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
11299 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
11301 MOV #1778,X \ RC5_Period * 1us
11302 MOV #14,W \ count of loop
11304 \ ******************************\
11305 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
11306 \ ******************************\ |
11307 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
11308 \ RC5_Compute_3/4_Period: \ |
11309 RRUM #1,X \ X=1/2 cycle |
11312 ADD X,Y \ Y=3/4 cycle
11313 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
11315 \ ******************************\
11316 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
11317 \ ******************************\
11318 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11319 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
11320 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11321 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11322 SUB #1,W \ decrement count loop
11323 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
11324 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11325 0<> WHILE \ ----> out of loop ----+
11326 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
11328 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
11329 CMP Y,X \ 1 | cycle time out of bound ?
11330 U>= IF \ 2 ^ | yes:
11331 BIC #$30,&RC5_TIM_CTL \ | | stop timer
11332 GOTO FW1 \ | | quit on truncated RC5 message
11334 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
11336 REPEAT \ ----> loop back --+ | with X = new RC5_period value
11337 \ ******************************\ |
11338 \ RC5_SampleEndOf: \ <---------------------+
11339 \ ******************************\
11340 BIC #$30,&RC5_TIM_CTL \ stop timer
11341 \ ******************************\
11342 \ RC5_ComputeNewRC5word \
11343 \ ******************************\
11344 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
11345 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
11346 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
11347 \ ******************************\
11348 \ RC5_ComputeC6bit \
11349 \ ******************************\
11350 BIT #BIT14,T \ test /C6 bit in T
11351 0= IF BIS #BIT6,X \ set C6 bit in X
11352 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
11353 \ ******************************\
11354 \ RC5_CommandByteIsDone \ -- BASE RC5_code
11355 \ ******************************\
11356 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
11357 \ ******************************\
11358 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
11359 XOR @RSP,T \ (new XOR old) Toggle bits
11360 BIT #UF10,T \ repeated RC5_command ?
11361 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
11362 XOR #UF10,0(RSP) \ 5 toggle bit memory
11363 \ ******************************\
11364 \ Display IR_RC5 code \
11365 \ ******************************\
11366 SUB #8,PSP \ TOS -- x x x x TOS
11367 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
11368 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
11369 MOV #$10,&BASEADR \ set hexadecimal base
11370 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
11371 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
11372 LO2HI \ switch from assembler to FORTH
11373 LCD_CLEAR \ set LCD cursor at home
11374 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
11375 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
11376 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
11377 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
11378 HI2LO \ -- switch from FORTH to assembler
11379 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
11380 MOV @PSP+,TOS \ -- TOS
11382 MOV @RSP+,SR \ restore SR flags
11383 BIC #%1111_1000,SR \ but force CPU Active Mode
11384 RET \ (instead of RETI)
11388 \ ------------------------------\
11389 HDNCODE STOP_R2L \ define new STOP_APP
11390 \ ------------------------------\
11391 CMP #RET_ADR,&{RC5TOLCD}+8 \
11392 0<> IF \ if previous START executing
11393 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
11394 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
11395 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
11396 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
11397 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
11398 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
11399 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
11400 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
11401 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
11402 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
11407 \ ------------------------------\
11409 \ ------------------------------\
11410 BW1 \ <-- INI_R2L for some events
11412 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
11414 ." RC5toLCD is removed,"
11415 ." type START to restart"
11418 \ ------------------------------\
11420 \ ------------------------------\
11421 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
11422 \ ------------------------------\
11424 \ ------------------------------\
11425 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
11426 \ ------------------------------\
11427 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
11428 \ ------------------------------\
11429 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
11430 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
11432 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
11433 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
11435 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
11436 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
11437 \ CMP #4,TOS \ hardware RST
11438 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
11439 \ CMP #2,TOS \ Power_ON event
11440 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11442 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11444 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11446 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11447 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
11448 \ ------------------------------\
11449 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
11450 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11451 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11452 \ -- \ID input divider \ 10 = /4
11453 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11454 \ - \TBCLR TimerB Clear
11457 \ -------------------------------\
11458 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11459 \ -- \CM Capture Mode
11464 \ --- \OUTMOD \ 011 = set/reset
11470 \ -------------------------------\
11472 \ -------------------------------\
11474 \ ------------------------------\
11475 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11476 \ ------------------------------\
11477 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11478 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11479 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
11480 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11482 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
11483 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11485 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
11486 \ ------------------------------\
11487 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11488 \ ------------------------------\
11489 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
11490 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11491 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11492 \ ------------------------------\
11493 BIS.B #LCDVo,&LCDVo_DIR \
11494 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
11495 \ ------------------------------\
11496 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11497 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11498 \ ------------------------------\
11499 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11500 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11501 \ ******************************\
11503 \ ******************************\
11504 BIS.B #RC5,&IR_IE \ enable RC5_Int
11505 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11506 \ ******************************\
11507 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11508 \ ******************************\
11509 \ %01 0001 0100 \ TAxCTL
11510 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
11511 \ -- \ ID divided by 1
11512 \ -- \ MC MODE = up to TAxCCRn
11513 \ - \ TACLR clear timer count
11516 \ ------------------------------\
11517 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
11518 \ ------------------------------\
11520 \ --- \ TAIDEX pre divisor
11521 \ ------------------------------\
11522 \ %0000 0000 0000 0101 \ TAxCCR0
11523 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11524 \ ------------------------------\
11525 \ %0000 0000 0001 0000 \ TAxCCTL0
11526 \ - \ CAP capture/compare mode = compare
11529 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
11530 \ ------------------------------\
11531 \ define LPM mode for ACCEPT \
11532 \ ------------------------------\
11533 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
11534 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11535 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11536 \ ------------------------------\
11538 \ ------------------------------\
11540 \ ------------------------------\
11541 #1000 20_US \ 1- wait 20 ms
11542 %011 TOP_LCD \ 2- send DB5=DB4=1
11543 #205 20_US \ 3- wait 4,1 ms
11544 %011 TOP_LCD \ 4- send again DB5=DB4=1
11545 #5 20_US \ 5- wait 0,1 ms
11546 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11547 #2 20_US \ wait 40 us = LCD cycle
11548 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11549 #2 20_US \ wait 40 us = LCD cycle
11550 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11551 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11552 LCD_CLEAR \ 10- "LCD_Clear"
11553 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11554 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11555 LCD_CLEAR \ 10- "LCD_Clear"
11556 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11557 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11558 CR ." I love you" \ display message on LCD
11559 ['] CR >BODY IS CR \ CR executes its default value
11560 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11561 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11564 \ ------------------------------\
11566 \ ------------------------------\
11567 CODE START \ this routine replaces WARM and COLD default values by these of this application.
11568 \ ------------------------------\
11569 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
11570 0= IF \ if not done, customizes MARKER_DOES
11571 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
11572 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
11573 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
11574 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
11575 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11576 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
11577 MOV #RC5_INT,&IR_VEC \ init interrupt vector
11578 MOV #INI_R2L,PC \ then execute new INI_APP, without return
11582 \ ------------------------------\
11585 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11587 MARKER {RC5TOLCD} \ restore the state before MARKER definition
11588 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
11589 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
11590 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
11591 \ {RC5TOLCD}+14: make room to save previous IR_VEC
11593 [UNDEFINED] CONSTANT [IF]
11594 \ https://forth-standard.org/standard/core/CONSTANT
11595 \ CONSTANT <name> n -- define a Forth CONSTANT
11599 MOV TOS,-2(W) \ PFA = n
11606 [UNDEFINED] STATE [IF]
11607 \ https://forth-standard.org/standard/core/STATE
11608 \ STATE -- a-addr holds compiler state
11609 STATEADR CONSTANT STATE
11613 \ https://forth-standard.org/standard/core/Equal
11614 \ = x1 x2 -- flag test x1=x2
11621 XOR #-1,TOS \ 1 flag Z = 1
11626 [UNDEFINED] IF [IF] \ define IF and THEN
11627 \ https://forth-standard.org/standard/core/IF
11628 \ IF -- IFadr initialize conditional forward branch
11629 CODE IF \ immediate
11632 MOV &DP,TOS \ -- HERE
11633 ADD #4,&DP \ compile one word, reserve one word
11634 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
11635 ADD #2,TOS \ -- HERE+2=IFadr
11639 \ https://forth-standard.org/standard/core/THEN
11640 \ THEN IFadr -- resolve forward branch
11641 CODE THEN \ immediate
11642 MOV &DP,0(TOS) \ -- IFadr
11648 [UNDEFINED] ELSE [IF]
11649 \ https://forth-standard.org/standard/core/ELSE
11650 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
11651 CODE ELSE \ immediate
11652 ADD #4,&DP \ make room to compile two words
11653 MOV &DP,W \ W=HERE+4
11655 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
11657 MOV W,TOS \ -- ELSEadr
11662 [UNDEFINED] IS [IF] \ define DEFER! and IS
11664 \ https://forth-standard.org/standard/core/DEFERStore
11665 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
11666 CODE DEFER! \ xt2 xt1 --
11667 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
11672 \ https://forth-standard.org/standard/core/IS
11675 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
11676 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
11677 \ or in a definition : ... ['] U. IS DISPLAY ...
11678 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
11680 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
11684 IF POSTPONE ['] POSTPONE DEFER!
11690 [UNDEFINED] >BODY [IF]
11691 \ https://forth-standard.org/standard/core/toBODY
11692 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
11699 \ CODE 20uS \ n -- 8MHz version
11700 \ BEGIN \ 4 + 16 ~ loop
11701 \ MOV #39,rDOCON \ 39
11708 \ MOV #XDOCON,rDOCON \ 2
11713 CODE 20_US \ n -- n * 20 us
11714 BEGIN \ here we presume that LCD_TIM_IFG = 1...
11716 BIT #1,&LCD_TIM_CTL \ 3
11717 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
11718 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
11720 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
11725 CODE TOP_LCD \ LCD Sample
11726 \ \ if write : %xxxx_WWWW --
11727 \ \ if read : -- %0000_RRRR
11728 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11729 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11730 0= IF \ write LCD bits pattern
11731 AND.B #LCD_DB,TOS \
11732 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11733 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11736 THEN \ read LCD bits pattern
11739 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11740 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11741 AND.B #LCD_DB,TOS \
11745 CODE LCD_WRC \ char -- Write Char
11746 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11748 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
11749 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
11750 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11751 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11752 COLON \ high level word starts here
11753 TOP_LCD 2 20_US \ write high nibble first
11757 CODE LCD_WRF \ func -- Write Fonction
11758 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11762 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
11763 : LCD_HOME $02 LCD_WRF 100 20_us ;
11765 \ [UNDEFINED] OR [IF]
11767 \ \ https://forth-standard.org/standard/core/OR
11768 \ \ C OR x1 x2 -- x3 logical OR
11776 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
11777 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
11778 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
11779 \ : LCD_FN_SET $20 OR LCD_WrF ;
11780 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
11781 \ : LCD_GOTO $80 OR LCD_WrF ;
11784 \ CODE LCD_RDS \ -- status Read Status
11785 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11786 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11787 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11788 \ COLON \ starts a FORTH word
11789 \ TOP_LCD 2 20_us \ -- %0000_HHHH
11790 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
11791 \ HI2LO \ switch from FORTH to assembler
11792 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
11793 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
11794 \ MOV @RSP+,IP \ restore IP saved by COLON
11798 \ CODE LCD_RDC \ -- char Read Char
11799 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11804 \ ******************************\
11805 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11806 \ ******************************\
11807 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
11808 BIT.B #SW2,&SW2_IN \ test switch S2
11809 0= IF \ case of switch S2 pressed
11810 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
11812 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
11815 BIT.B #SW1,&SW1_IN \ test switch S1 input
11816 0= IF \ case of Switch S1 pressed
11817 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
11819 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
11826 \ ******************************\
11827 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
11828 \ ******************************\
11829 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11830 \ ******************************\
11831 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11832 \ \ SMclock = 8|16|24 MHz
11833 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
11834 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
11835 \ \ SR(9)=new Toggle bit memory (ADD on)
11836 \ ******************************\
11837 \ RC5_FirstStartBitHalfCycle: \
11838 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
11839 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
11840 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
11842 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
11843 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
11845 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
11846 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
11848 MOV #1778,X \ RC5_Period * 1us
11849 MOV #14,W \ count of loop
11851 \ ******************************\
11852 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
11853 \ ******************************\ |
11854 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
11855 \ RC5_Compute_3/4_Period: \ |
11856 RRUM #1,X \ X=1/2 cycle |
11859 ADD X,Y \ Y=3/4 cycle
11860 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
11862 \ ******************************\
11863 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
11864 \ ******************************\
11865 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11866 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
11867 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11868 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11869 SUB #1,W \ decrement count loop
11870 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
11871 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11872 0<> WHILE \ ----> out of loop ----+
11873 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
11875 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
11876 CMP Y,X \ 1 | cycle time out of bound ?
11877 U>= IF \ 2 ^ | yes:
11878 BIC #$30,&RC5_TIM_CTL \ | | stop timer
11879 GOTO FW1 \ | | quit on truncated RC5 message
11881 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
11883 REPEAT \ ----> loop back --+ | with X = new RC5_period value
11884 \ ******************************\ |
11885 \ RC5_SampleEndOf: \ <---------------------+
11886 \ ******************************\
11887 BIC #$30,&RC5_TIM_CTL \ stop timer
11888 \ ******************************\
11889 \ RC5_ComputeNewRC5word \
11890 \ ******************************\
11891 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
11892 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
11893 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
11894 \ ******************************\
11895 \ RC5_ComputeC6bit \
11896 \ ******************************\
11897 BIT #BIT14,T \ test /C6 bit in T
11898 0= IF BIS #BIT6,X \ set C6 bit in X
11899 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
11900 \ ******************************\
11901 \ RC5_CommandByteIsDone \ -- BASE RC5_code
11902 \ ******************************\
11903 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
11904 \ ******************************\
11905 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
11906 XOR @RSP,T \ (new XOR old) Toggle bits
11907 BIT #UF10,T \ repeated RC5_command ?
11908 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
11909 XOR #UF10,0(RSP) \ 5 toggle bit memory
11910 \ ******************************\
11911 \ Display IR_RC5 code \
11912 \ ******************************\
11913 SUB #8,PSP \ TOS -- x x x x TOS
11914 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
11915 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
11916 MOV #$10,&BASEADR \ set hexadecimal base
11917 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
11918 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
11919 LO2HI \ switch from assembler to FORTH
11920 LCD_CLEAR \ set LCD cursor at home
11921 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
11922 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
11923 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
11924 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
11925 HI2LO \ -- switch from FORTH to assembler
11926 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
11927 MOV @PSP+,TOS \ -- TOS
11929 MOV @RSP+,SR \ restore SR flags
11930 BIC #%1111_1000,SR \ but force CPU Active Mode
11931 RET \ (instead of RETI)
11935 \ ------------------------------\
11936 HDNCODE STOP_R2L \ define new STOP_APP
11937 \ ------------------------------\
11938 CMP #RET_ADR,&{RC5TOLCD}+8 \
11939 0<> IF \ if previous START executing
11940 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
11941 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
11942 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
11943 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
11944 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
11945 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
11946 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
11947 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
11948 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
11949 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
11954 \ ------------------------------\
11956 \ ------------------------------\
11957 BW1 \ <-- INI_R2L for some events
11959 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
11961 ." RC5toLCD is removed,"
11962 ." type START to restart"
11965 \ ------------------------------\
11967 \ ------------------------------\
11968 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
11969 \ ------------------------------\
11971 \ ------------------------------\
11972 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
11973 \ ------------------------------\
11974 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
11975 \ ------------------------------\
11976 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
11977 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
11979 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
11980 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
11982 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
11983 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
11984 \ CMP #4,TOS \ hardware RST
11985 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
11986 \ CMP #2,TOS \ Power_ON event
11987 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11989 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11991 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11993 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11994 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
11995 \ ------------------------------\
11996 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
11997 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11998 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11999 \ -- \ID input divider \ 10 = /4
12000 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12001 \ - \TBCLR TimerB Clear
12004 \ -------------------------------\
12005 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12006 \ -- \CM Capture Mode
12011 \ --- \OUTMOD \ 011 = set/reset
12017 \ -------------------------------\
12019 \ -------------------------------\
12021 \ ------------------------------\
12022 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12023 \ ------------------------------\
12024 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12025 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12026 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
12027 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12029 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
12030 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12032 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
12033 \ ------------------------------\
12034 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12035 \ ------------------------------\
12036 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
12037 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12038 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12039 \ ------------------------------\
12040 BIS.B #LCDVo,&LCDVo_DIR \
12041 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
12042 \ ------------------------------\
12043 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12044 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12045 \ ------------------------------\
12046 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12047 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12048 \ ******************************\
12050 \ ******************************\
12051 BIS.B #RC5,&IR_IE \ enable RC5_Int
12052 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12053 \ ******************************\
12054 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12055 \ ******************************\
12056 \ %01 0001 0100 \ TAxCTL
12057 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
12058 \ -- \ ID divided by 1
12059 \ -- \ MC MODE = up to TAxCCRn
12060 \ - \ TACLR clear timer count
12063 \ ------------------------------\
12064 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
12065 \ ------------------------------\
12067 \ --- \ TAIDEX pre divisor
12068 \ ------------------------------\
12069 \ %0000 0000 0000 0101 \ TAxCCR0
12070 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12071 \ ------------------------------\
12072 \ %0000 0000 0001 0000 \ TAxCCTL0
12073 \ - \ CAP capture/compare mode = compare
12076 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
12077 \ ------------------------------\
12078 \ define LPM mode for ACCEPT \
12079 \ ------------------------------\
12080 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
12081 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12082 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12083 \ ------------------------------\
12085 \ ------------------------------\
12087 \ ------------------------------\
12088 #1000 20_US \ 1- wait 20 ms
12089 %011 TOP_LCD \ 2- send DB5=DB4=1
12090 #205 20_US \ 3- wait 4,1 ms
12091 %011 TOP_LCD \ 4- send again DB5=DB4=1
12092 #5 20_US \ 5- wait 0,1 ms
12093 %011 TOP_LCD \ 6- send again again DB5=DB4=1
12094 #2 20_US \ wait 40 us = LCD cycle
12095 %010 TOP_LCD \ 7- send DB5=1 DB4=0
12096 #2 20_US \ wait 40 us = LCD cycle
12097 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12098 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12099 LCD_CLEAR \ 10- "LCD_Clear"
12100 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12101 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12102 LCD_CLEAR \ 10- "LCD_Clear"
12103 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12104 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12105 CR ." I love you" \ display message on LCD
12106 ['] CR >BODY IS CR \ CR executes its default value
12107 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
12108 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
12111 \ ------------------------------\
12113 \ ------------------------------\
12114 CODE START \ this routine replaces WARM and COLD default values by these of this application.
12115 \ ------------------------------\
12116 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
12117 0= IF \ if not done, customizes MARKER_DOES
12118 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
12119 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
12120 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
12121 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
12122 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12123 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
12124 MOV #RC5_INT,&IR_VEC \ init interrupt vector
12125 MOV #INI_R2L,PC \ then execute new INI_APP, without return
12129 \ ------------------------------\
12132 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
12134 MARKER {RC5TOLCD} \ restore the state before MARKER definition
12135 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
12136 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
12137 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
12138 \ {RC5TOLCD}+14: make room to save previous IR_VEC
12140 [UNDEFINED] CONSTANT [IF]
12141 \ https://forth-standard.org/standard/core/CONSTANT
12142 \ CONSTANT <name> n -- define a Forth CONSTANT
12146 MOV TOS,-2(W) \ PFA = n
12153 [UNDEFINED] STATE [IF]
12154 \ https://forth-standard.org/standard/core/STATE
12155 \ STATE -- a-addr holds compiler state
12156 STATEADR CONSTANT STATE
12160 \ https://forth-standard.org/standard/core/Equal
12161 \ = x1 x2 -- flag test x1=x2
12168 XOR #-1,TOS \ 1 flag Z = 1
12173 [UNDEFINED] IF [IF] \ define IF and THEN
12174 \ https://forth-standard.org/standard/core/IF
12175 \ IF -- IFadr initialize conditional forward branch
12176 CODE IF \ immediate
12179 MOV &DP,TOS \ -- HERE
12180 ADD #4,&DP \ compile one word, reserve one word
12181 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
12182 ADD #2,TOS \ -- HERE+2=IFadr
12186 \ https://forth-standard.org/standard/core/THEN
12187 \ THEN IFadr -- resolve forward branch
12188 CODE THEN \ immediate
12189 MOV &DP,0(TOS) \ -- IFadr
12195 [UNDEFINED] ELSE [IF]
12196 \ https://forth-standard.org/standard/core/ELSE
12197 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
12198 CODE ELSE \ immediate
12199 ADD #4,&DP \ make room to compile two words
12200 MOV &DP,W \ W=HERE+4
12202 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
12204 MOV W,TOS \ -- ELSEadr
12209 [UNDEFINED] IS [IF] \ define DEFER! and IS
12211 \ https://forth-standard.org/standard/core/DEFERStore
12212 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
12213 CODE DEFER! \ xt2 xt1 --
12214 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
12219 \ https://forth-standard.org/standard/core/IS
12222 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
12223 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
12224 \ or in a definition : ... ['] U. IS DISPLAY ...
12225 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
12227 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
12231 IF POSTPONE ['] POSTPONE DEFER!
12237 [UNDEFINED] >BODY [IF]
12238 \ https://forth-standard.org/standard/core/toBODY
12239 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
12246 \ CODE 20uS \ n -- 8MHz version
12247 \ BEGIN \ 4 + 16 ~ loop
12248 \ MOV #39,rDOCON \ 39
12255 \ MOV #XDOCON,rDOCON \ 2
12260 CODE 20_US \ n -- n * 20 us
12261 BEGIN \ here we presume that LCD_TIM_IFG = 1...
12263 BIT #1,&LCD_TIM_CTL \ 3
12264 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
12265 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
12267 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
12272 CODE TOP_LCD \ LCD Sample
12273 \ \ if write : %xxxx_WWWW --
12274 \ \ if read : -- %0000_RRRR
12275 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12276 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12277 0= IF \ write LCD bits pattern
12278 AND.B #LCD_DB,TOS \
12279 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12280 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12283 THEN \ read LCD bits pattern
12286 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12287 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12288 AND.B #LCD_DB,TOS \
12292 CODE LCD_WRC \ char -- Write Char
12293 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12295 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
12296 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
12297 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12298 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12299 COLON \ high level word starts here
12300 TOP_LCD 2 20_US \ write high nibble first
12304 CODE LCD_WRF \ func -- Write Fonction
12305 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12309 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
12310 : LCD_HOME $02 LCD_WRF 100 20_us ;
12312 \ [UNDEFINED] OR [IF]
12314 \ \ https://forth-standard.org/standard/core/OR
12315 \ \ C OR x1 x2 -- x3 logical OR
12323 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
12324 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
12325 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
12326 \ : LCD_FN_SET $20 OR LCD_WrF ;
12327 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
12328 \ : LCD_GOTO $80 OR LCD_WrF ;
12331 \ CODE LCD_RDS \ -- status Read Status
12332 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12333 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12334 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12335 \ COLON \ starts a FORTH word
12336 \ TOP_LCD 2 20_us \ -- %0000_HHHH
12337 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
12338 \ HI2LO \ switch from FORTH to assembler
12339 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
12340 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
12341 \ MOV @RSP+,IP \ restore IP saved by COLON
12345 \ CODE LCD_RDC \ -- char Read Char
12346 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12351 \ ******************************\
12352 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12353 \ ******************************\
12354 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12355 BIT.B #SW2,&SW2_IN \ test switch S2
12356 0= IF \ case of switch S2 pressed
12357 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12359 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12362 BIT.B #SW1,&SW1_IN \ test switch S1 input
12363 0= IF \ case of Switch S1 pressed
12364 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12366 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12373 \ ******************************\
12374 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
12375 \ ******************************\
12376 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12377 \ ******************************\
12378 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12379 \ \ SMclock = 8|16|24 MHz
12380 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12381 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12382 \ \ SR(9)=new Toggle bit memory (ADD on)
12383 \ ******************************\
12384 \ RC5_FirstStartBitHalfCycle: \
12385 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12386 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12387 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12389 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12390 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12392 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12393 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12395 MOV #1778,X \ RC5_Period * 1us
12396 MOV #14,W \ count of loop
12398 \ ******************************\
12399 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12400 \ ******************************\ |
12401 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12402 \ RC5_Compute_3/4_Period: \ |
12403 RRUM #1,X \ X=1/2 cycle |
12406 ADD X,Y \ Y=3/4 cycle
12407 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12409 \ ******************************\
12410 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12411 \ ******************************\
12412 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12413 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12414 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12415 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12416 SUB #1,W \ decrement count loop
12417 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12418 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12419 0<> WHILE \ ----> out of loop ----+
12420 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12422 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12423 CMP Y,X \ 1 | cycle time out of bound ?
12424 U>= IF \ 2 ^ | yes:
12425 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12426 GOTO FW1 \ | | quit on truncated RC5 message
12428 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12430 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12431 \ ******************************\ |
12432 \ RC5_SampleEndOf: \ <---------------------+
12433 \ ******************************\
12434 BIC #$30,&RC5_TIM_CTL \ stop timer
12435 \ ******************************\
12436 \ RC5_ComputeNewRC5word \
12437 \ ******************************\
12438 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12439 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12440 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12441 \ ******************************\
12442 \ RC5_ComputeC6bit \
12443 \ ******************************\
12444 BIT #BIT14,T \ test /C6 bit in T
12445 0= IF BIS #BIT6,X \ set C6 bit in X
12446 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12447 \ ******************************\
12448 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12449 \ ******************************\
12450 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
12451 \ ******************************\
12452 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
12453 XOR @RSP,T \ (new XOR old) Toggle bits
12454 BIT #UF10,T \ repeated RC5_command ?
12455 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
12456 XOR #UF10,0(RSP) \ 5 toggle bit memory
12457 \ ******************************\
12458 \ Display IR_RC5 code \
12459 \ ******************************\
12460 SUB #8,PSP \ TOS -- x x x x TOS
12461 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
12462 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
12463 MOV #$10,&BASEADR \ set hexadecimal base
12464 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
12465 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
12466 LO2HI \ switch from assembler to FORTH
12467 LCD_CLEAR \ set LCD cursor at home
12468 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
12469 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
12470 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
12471 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
12472 HI2LO \ -- switch from FORTH to assembler
12473 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
12474 MOV @PSP+,TOS \ -- TOS
12476 MOV @RSP+,SR \ restore SR flags
12477 BIC #%1111_1000,SR \ but force CPU Active Mode
12478 RET \ (instead of RETI)
12482 \ ------------------------------\
12483 HDNCODE STOP_R2L \ define new STOP_APP
12484 \ ------------------------------\
12485 CMP #RET_ADR,&{RC5TOLCD}+8 \
12486 0<> IF \ if previous START executing
12487 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
12488 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
12489 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
12490 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
12491 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
12492 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
12493 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
12494 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
12495 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
12496 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
12501 \ ------------------------------\
12503 \ ------------------------------\
12504 BW1 \ <-- INI_R2L for some events
12506 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
12508 ." RC5toLCD is removed,"
12509 ." type START to restart"
12512 \ ------------------------------\
12514 \ ------------------------------\
12515 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
12516 \ ------------------------------\
12518 \ ------------------------------\
12519 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
12520 \ ------------------------------\
12521 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
12522 \ ------------------------------\
12523 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
12524 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
12526 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
12527 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
12529 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
12530 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
12531 \ CMP #4,TOS \ hardware RST
12532 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
12533 \ CMP #2,TOS \ Power_ON event
12534 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
12536 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
12538 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
12540 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
12541 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
12542 \ ------------------------------\
12543 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
12544 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12545 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12546 \ -- \ID input divider \ 10 = /4
12547 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12548 \ - \TBCLR TimerB Clear
12551 \ -------------------------------\
12552 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12553 \ -- \CM Capture Mode
12558 \ --- \OUTMOD \ 011 = set/reset
12564 \ -------------------------------\
12566 \ -------------------------------\
12568 \ ------------------------------\
12569 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12570 \ ------------------------------\
12571 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12572 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12573 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
12574 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12576 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
12577 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12579 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
12580 \ ------------------------------\
12581 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12582 \ ------------------------------\
12583 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
12584 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12585 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12586 \ ------------------------------\
12587 BIS.B #LCDVo,&LCDVo_DIR \
12588 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
12589 \ ------------------------------\
12590 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12591 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12592 \ ------------------------------\
12593 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12594 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12595 \ ******************************\
12597 \ ******************************\
12598 BIS.B #RC5,&IR_IE \ enable RC5_Int
12599 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12600 \ ******************************\
12601 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12602 \ ******************************\
12603 \ %01 0001 0100 \ TAxCTL
12604 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
12605 \ -- \ ID divided by 1
12606 \ -- \ MC MODE = up to TAxCCRn
12607 \ - \ TACLR clear timer count
12610 \ ------------------------------\
12611 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
12612 \ ------------------------------\
12614 \ --- \ TAIDEX pre divisor
12615 \ ------------------------------\
12616 \ %0000 0000 0000 0101 \ TAxCCR0
12617 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12618 \ ------------------------------\
12619 \ %0000 0000 0001 0000 \ TAxCCTL0
12620 \ - \ CAP capture/compare mode = compare
12623 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
12624 \ ------------------------------\
12625 \ define LPM mode for ACCEPT \
12626 \ ------------------------------\
12627 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
12628 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12629 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12630 \ ------------------------------\
12632 \ ------------------------------\
12634 \ ------------------------------\
12635 #1000 20_US \ 1- wait 20 ms
12636 %011 TOP_LCD \ 2- send DB5=DB4=1
12637 #205 20_US \ 3- wait 4,1 ms
12638 %011 TOP_LCD \ 4- send again DB5=DB4=1
12639 #5 20_US \ 5- wait 0,1 ms
12640 %011 TOP_LCD \ 6- send again again DB5=DB4=1
12641 #2 20_US \ wait 40 us = LCD cycle
12642 %010 TOP_LCD \ 7- send DB5=1 DB4=0
12643 #2 20_US \ wait 40 us = LCD cycle
12644 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12645 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12646 LCD_CLEAR \ 10- "LCD_Clear"
12647 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12648 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12649 LCD_CLEAR \ 10- "LCD_Clear"
12650 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12651 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12652 CR ." I love you" \ display message on LCD
12653 ['] CR >BODY IS CR \ CR executes its default value
12654 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
12655 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
12658 \ ------------------------------\
12660 \ ------------------------------\
12661 CODE START \ this routine replaces WARM and COLD default values by these of this application.
12662 \ ------------------------------\
12663 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
12664 0= IF \ if not done, customizes MARKER_DOES
12665 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
12666 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
12667 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
12668 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
12669 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12670 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
12671 MOV #RC5_INT,&IR_VEC \ init interrupt vector
12672 MOV #INI_R2L,PC \ then execute new INI_APP, without return
12676 \ ------------------------------\
12679 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
12681 MARKER {RC5TOLCD} \ restore the state before MARKER definition
12682 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
12683 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
12684 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
12685 \ {RC5TOLCD}+14: make room to save previous IR_VEC
12687 [UNDEFINED] CONSTANT [IF]
12688 \ https://forth-standard.org/standard/core/CONSTANT
12689 \ CONSTANT <name> n -- define a Forth CONSTANT
12693 MOV TOS,-2(W) \ PFA = n
12700 [UNDEFINED] STATE [IF]
12701 \ https://forth-standard.org/standard/core/STATE
12702 \ STATE -- a-addr holds compiler state
12703 STATEADR CONSTANT STATE
12707 \ https://forth-standard.org/standard/core/Equal
12708 \ = x1 x2 -- flag test x1=x2
12715 XOR #-1,TOS \ 1 flag Z = 1
12720 [UNDEFINED] IF [IF] \ define IF and THEN
12721 \ https://forth-standard.org/standard/core/IF
12722 \ IF -- IFadr initialize conditional forward branch
12723 CODE IF \ immediate
12726 MOV &DP,TOS \ -- HERE
12727 ADD #4,&DP \ compile one word, reserve one word
12728 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
12729 ADD #2,TOS \ -- HERE+2=IFadr
12733 \ https://forth-standard.org/standard/core/THEN
12734 \ THEN IFadr -- resolve forward branch
12735 CODE THEN \ immediate
12736 MOV &DP,0(TOS) \ -- IFadr
12742 [UNDEFINED] ELSE [IF]
12743 \ https://forth-standard.org/standard/core/ELSE
12744 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
12745 CODE ELSE \ immediate
12746 ADD #4,&DP \ make room to compile two words
12747 MOV &DP,W \ W=HERE+4
12749 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
12751 MOV W,TOS \ -- ELSEadr
12756 [UNDEFINED] IS [IF] \ define DEFER! and IS
12758 \ https://forth-standard.org/standard/core/DEFERStore
12759 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
12760 CODE DEFER! \ xt2 xt1 --
12761 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
12766 \ https://forth-standard.org/standard/core/IS
12769 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
12770 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
12771 \ or in a definition : ... ['] U. IS DISPLAY ...
12772 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
12774 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
12778 IF POSTPONE ['] POSTPONE DEFER!
12784 [UNDEFINED] >BODY [IF]
12785 \ https://forth-standard.org/standard/core/toBODY
12786 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
12793 \ CODE 20uS \ n -- 8MHz version
12794 \ BEGIN \ 4 + 16 ~ loop
12795 \ MOV #39,rDOCON \ 39
12802 \ MOV #XDOCON,rDOCON \ 2
12807 CODE 20_US \ n -- n * 20 us
12808 BEGIN \ here we presume that LCD_TIM_IFG = 1...
12810 BIT #1,&LCD_TIM_CTL \ 3
12811 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
12812 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
12814 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
12819 CODE TOP_LCD \ LCD Sample
12820 \ \ if write : %xxxx_WWWW --
12821 \ \ if read : -- %0000_RRRR
12822 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12823 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12824 0= IF \ write LCD bits pattern
12825 AND.B #LCD_DB,TOS \
12826 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12827 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12830 THEN \ read LCD bits pattern
12833 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12834 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12835 AND.B #LCD_DB,TOS \
12839 CODE LCD_WRC \ char -- Write Char
12840 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12842 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
12843 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
12844 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12845 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12846 COLON \ high level word starts here
12847 TOP_LCD 2 20_US \ write high nibble first
12851 CODE LCD_WRF \ func -- Write Fonction
12852 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12856 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
12857 : LCD_HOME $02 LCD_WRF 100 20_us ;
12859 \ [UNDEFINED] OR [IF]
12861 \ \ https://forth-standard.org/standard/core/OR
12862 \ \ C OR x1 x2 -- x3 logical OR
12870 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
12871 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
12872 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
12873 \ : LCD_FN_SET $20 OR LCD_WrF ;
12874 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
12875 \ : LCD_GOTO $80 OR LCD_WrF ;
12878 \ CODE LCD_RDS \ -- status Read Status
12879 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12880 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12881 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12882 \ COLON \ starts a FORTH word
12883 \ TOP_LCD 2 20_us \ -- %0000_HHHH
12884 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
12885 \ HI2LO \ switch from FORTH to assembler
12886 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
12887 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
12888 \ MOV @RSP+,IP \ restore IP saved by COLON
12892 \ CODE LCD_RDC \ -- char Read Char
12893 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12898 \ ******************************\
12899 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12900 \ ******************************\
12901 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12902 BIT.B #SW2,&SW2_IN \ test switch S2
12903 0= IF \ case of switch S2 pressed
12904 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12906 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12909 BIT.B #SW1,&SW1_IN \ test switch S1 input
12910 0= IF \ case of Switch S1 pressed
12911 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12913 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12920 \ ******************************\
12921 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
12922 \ ******************************\
12923 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12924 \ ******************************\
12925 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12926 \ \ SMclock = 8|16|24 MHz
12927 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12928 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12929 \ \ SR(9)=new Toggle bit memory (ADD on)
12930 \ ******************************\
12931 \ RC5_FirstStartBitHalfCycle: \
12932 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12933 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12934 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12936 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12937 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12939 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12940 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12942 MOV #1778,X \ RC5_Period * 1us
12943 MOV #14,W \ count of loop
12945 \ ******************************\
12946 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12947 \ ******************************\ |
12948 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12949 \ RC5_Compute_3/4_Period: \ |
12950 RRUM #1,X \ X=1/2 cycle |
12953 ADD X,Y \ Y=3/4 cycle
12954 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12956 \ ******************************\
12957 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12958 \ ******************************\
12959 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12960 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12961 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12962 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12963 SUB #1,W \ decrement count loop
12964 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12965 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12966 0<> WHILE \ ----> out of loop ----+
12967 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12969 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12970 CMP Y,X \ 1 | cycle time out of bound ?
12971 U>= IF \ 2 ^ | yes:
12972 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12973 GOTO FW1 \ | | quit on truncated RC5 message
12975 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12977 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12978 \ ******************************\ |
12979 \ RC5_SampleEndOf: \ <---------------------+
12980 \ ******************************\
12981 BIC #$30,&RC5_TIM_CTL \ stop timer
12982 \ ******************************\
12983 \ RC5_ComputeNewRC5word \
12984 \ ******************************\
12985 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12986 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12987 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12988 \ ******************************\
12989 \ RC5_ComputeC6bit \
12990 \ ******************************\
12991 BIT #BIT14,T \ test /C6 bit in T
12992 0= IF BIS #BIT6,X \ set C6 bit in X
12993 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12994 \ ******************************\
12995 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12996 \ ******************************\
12997 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
12998 \ ******************************\
12999 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
13000 XOR @RSP,T \ (new XOR old) Toggle bits
13001 BIT #UF10,T \ repeated RC5_command ?
13002 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
13003 XOR #UF10,0(RSP) \ 5 toggle bit memory
13004 \ ******************************\
13005 \ Display IR_RC5 code \
13006 \ ******************************\
13007 SUB #8,PSP \ TOS -- x x x x TOS
13008 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
13009 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
13010 MOV #$10,&BASEADR \ set hexadecimal base
13011 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
13012 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
13013 LO2HI \ switch from assembler to FORTH
13014 LCD_CLEAR \ set LCD cursor at home
13015 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
13016 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
13017 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
13018 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
13019 HI2LO \ -- switch from FORTH to assembler
13020 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
13021 MOV @PSP+,TOS \ -- TOS
13023 MOV @RSP+,SR \ restore SR flags
13024 BIC #%1111_1000,SR \ but force CPU Active Mode
13025 RET \ (instead of RETI)
13029 \ ------------------------------\
13030 HDNCODE STOP_R2L \ define new STOP_APP
13031 \ ------------------------------\
13032 CMP #RET_ADR,&{RC5TOLCD}+8 \
13033 0<> IF \ if previous START executing
13034 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
13035 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
13036 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
13037 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
13038 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
13039 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
13040 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
13041 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
13042 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
13043 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
13048 \ ------------------------------\
13050 \ ------------------------------\
13051 BW1 \ <-- INI_R2L for some events
13053 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
13055 ." RC5toLCD is removed,"
13056 ." type START to restart"
13059 \ ------------------------------\
13061 \ ------------------------------\
13062 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
13063 \ ------------------------------\
13065 \ ------------------------------\
13066 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
13067 \ ------------------------------\
13068 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
13069 \ ------------------------------\
13070 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
13071 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
13073 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
13074 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
13076 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
13077 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
13078 \ CMP #4,TOS \ hardware RST
13079 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
13080 \ CMP #2,TOS \ Power_ON event
13081 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13083 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13085 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13087 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13088 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
13089 \ ------------------------------\
13090 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
13091 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13092 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13093 \ -- \ID input divider \ 10 = /4
13094 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
13095 \ - \TBCLR TimerB Clear
13098 \ -------------------------------\
13099 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13100 \ -- \CM Capture Mode
13105 \ --- \OUTMOD \ 011 = set/reset
13111 \ -------------------------------\
13113 \ -------------------------------\
13115 \ ------------------------------\
13116 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13117 \ ------------------------------\
13118 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13119 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13120 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
13121 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13123 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
13124 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13126 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
13127 \ ------------------------------\
13128 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13129 \ ------------------------------\
13130 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
13131 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13132 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13133 \ ------------------------------\
13134 BIS.B #LCDVo,&LCDVo_DIR \
13135 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
13136 \ ------------------------------\
13137 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13138 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13139 \ ------------------------------\
13140 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13141 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13142 \ ******************************\
13144 \ ******************************\
13145 BIS.B #RC5,&IR_IE \ enable RC5_Int
13146 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13147 \ ******************************\
13148 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13149 \ ******************************\
13150 \ %01 0001 0100 \ TAxCTL
13151 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
13152 \ -- \ ID divided by 1
13153 \ -- \ MC MODE = up to TAxCCRn
13154 \ - \ TACLR clear timer count
13157 \ ------------------------------\
13158 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
13159 \ ------------------------------\
13161 \ --- \ TAIDEX pre divisor
13162 \ ------------------------------\
13163 \ %0000 0000 0000 0101 \ TAxCCR0
13164 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13165 \ ------------------------------\
13166 \ %0000 0000 0001 0000 \ TAxCCTL0
13167 \ - \ CAP capture/compare mode = compare
13170 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
13171 \ ------------------------------\
13172 \ define LPM mode for ACCEPT \
13173 \ ------------------------------\
13174 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
13175 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13176 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13177 \ ------------------------------\
13179 \ ------------------------------\
13181 \ ------------------------------\
13182 #1000 20_US \ 1- wait 20 ms
13183 %011 TOP_LCD \ 2- send DB5=DB4=1
13184 #205 20_US \ 3- wait 4,1 ms
13185 %011 TOP_LCD \ 4- send again DB5=DB4=1
13186 #5 20_US \ 5- wait 0,1 ms
13187 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13188 #2 20_US \ wait 40 us = LCD cycle
13189 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13190 #2 20_US \ wait 40 us = LCD cycle
13191 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13192 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13193 LCD_CLEAR \ 10- "LCD_Clear"
13194 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13195 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13196 LCD_CLEAR \ 10- "LCD_Clear"
13197 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13198 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13199 CR ." I love you" \ display message on LCD
13200 ['] CR >BODY IS CR \ CR executes its default value
13201 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13202 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13205 \ ------------------------------\
13207 \ ------------------------------\
13208 CODE START \ this routine replaces WARM and COLD default values by these of this application.
13209 \ ------------------------------\
13210 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
13211 0= IF \ if not done, customizes MARKER_DOES
13212 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
13213 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
13214 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
13215 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
13216 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13217 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
13218 MOV #RC5_INT,&IR_VEC \ init interrupt vector
13219 MOV #INI_R2L,PC \ then execute new INI_APP, without return
13223 \ ------------------------------\
13226 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13228 MARKER {RC5TOLCD} \ restore the state before MARKER definition
13229 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
13230 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
13231 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
13232 \ {RC5TOLCD}+14: make room to save previous IR_VEC
13234 [UNDEFINED] CONSTANT [IF]
13235 \ https://forth-standard.org/standard/core/CONSTANT
13236 \ CONSTANT <name> n -- define a Forth CONSTANT
13240 MOV TOS,-2(W) \ PFA = n
13247 [UNDEFINED] STATE [IF]
13248 \ https://forth-standard.org/standard/core/STATE
13249 \ STATE -- a-addr holds compiler state
13250 STATEADR CONSTANT STATE
13254 \ https://forth-standard.org/standard/core/Equal
13255 \ = x1 x2 -- flag test x1=x2
13262 XOR #-1,TOS \ 1 flag Z = 1
13267 [UNDEFINED] IF [IF] \ define IF and THEN
13268 \ https://forth-standard.org/standard/core/IF
13269 \ IF -- IFadr initialize conditional forward branch
13270 CODE IF \ immediate
13273 MOV &DP,TOS \ -- HERE
13274 ADD #4,&DP \ compile one word, reserve one word
13275 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
13276 ADD #2,TOS \ -- HERE+2=IFadr
13280 \ https://forth-standard.org/standard/core/THEN
13281 \ THEN IFadr -- resolve forward branch
13282 CODE THEN \ immediate
13283 MOV &DP,0(TOS) \ -- IFadr
13289 [UNDEFINED] ELSE [IF]
13290 \ https://forth-standard.org/standard/core/ELSE
13291 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
13292 CODE ELSE \ immediate
13293 ADD #4,&DP \ make room to compile two words
13294 MOV &DP,W \ W=HERE+4
13296 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
13298 MOV W,TOS \ -- ELSEadr
13303 [UNDEFINED] IS [IF] \ define DEFER! and IS
13305 \ https://forth-standard.org/standard/core/DEFERStore
13306 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
13307 CODE DEFER! \ xt2 xt1 --
13308 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
13313 \ https://forth-standard.org/standard/core/IS
13316 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
13317 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
13318 \ or in a definition : ... ['] U. IS DISPLAY ...
13319 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
13321 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
13325 IF POSTPONE ['] POSTPONE DEFER!
13331 [UNDEFINED] >BODY [IF]
13332 \ https://forth-standard.org/standard/core/toBODY
13333 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
13340 \ CODE 20uS \ n -- 8MHz version
13341 \ BEGIN \ 4 + 16 ~ loop
13342 \ MOV #39,rDOCON \ 39
13349 \ MOV #XDOCON,rDOCON \ 2
13354 CODE 20_US \ n -- n * 20 us
13355 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13357 BIT #1,&LCD_TIM_CTL \ 3
13358 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13359 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13361 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13366 CODE TOP_LCD \ LCD Sample
13367 \ \ if write : %xxxx_WWWW --
13368 \ \ if read : -- %0000_RRRR
13369 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13370 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13371 0= IF \ write LCD bits pattern
13372 AND.B #LCD_DB,TOS \
13373 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13374 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13377 THEN \ read LCD bits pattern
13380 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13381 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13382 AND.B #LCD_DB,TOS \
13386 CODE LCD_WRC \ char -- Write Char
13387 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13389 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
13390 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
13391 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13392 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13393 COLON \ high level word starts here
13394 TOP_LCD 2 20_US \ write high nibble first
13398 CODE LCD_WRF \ func -- Write Fonction
13399 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13403 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13404 : LCD_HOME $02 LCD_WRF 100 20_us ;
13406 \ [UNDEFINED] OR [IF]
13408 \ \ https://forth-standard.org/standard/core/OR
13409 \ \ C OR x1 x2 -- x3 logical OR
13417 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
13418 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
13419 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
13420 \ : LCD_FN_SET $20 OR LCD_WrF ;
13421 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
13422 \ : LCD_GOTO $80 OR LCD_WrF ;
13425 \ CODE LCD_RDS \ -- status Read Status
13426 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13427 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13428 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13429 \ COLON \ starts a FORTH word
13430 \ TOP_LCD 2 20_us \ -- %0000_HHHH
13431 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
13432 \ HI2LO \ switch from FORTH to assembler
13433 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
13434 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
13435 \ MOV @RSP+,IP \ restore IP saved by COLON
13439 \ CODE LCD_RDC \ -- char Read Char
13440 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13445 \ ******************************\
13446 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13447 \ ******************************\
13448 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
13449 BIT.B #SW2,&SW2_IN \ test switch S2
13450 0= IF \ case of switch S2 pressed
13451 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13453 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
13456 BIT.B #SW1,&SW1_IN \ test switch S1 input
13457 0= IF \ case of Switch S1 pressed
13458 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13460 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13467 \ ******************************\
13468 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
13469 \ ******************************\
13470 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13471 \ ******************************\
13472 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13473 \ \ SMclock = 8|16|24 MHz
13474 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13475 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13476 \ \ SR(9)=new Toggle bit memory (ADD on)
13477 \ ******************************\
13478 \ RC5_FirstStartBitHalfCycle: \
13479 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13480 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
13481 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
13483 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
13484 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
13486 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
13487 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
13489 MOV #1778,X \ RC5_Period * 1us
13490 MOV #14,W \ count of loop
13492 \ ******************************\
13493 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
13494 \ ******************************\ |
13495 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
13496 \ RC5_Compute_3/4_Period: \ |
13497 RRUM #1,X \ X=1/2 cycle |
13500 ADD X,Y \ Y=3/4 cycle
13501 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
13503 \ ******************************\
13504 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
13505 \ ******************************\
13506 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13507 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
13508 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13509 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13510 SUB #1,W \ decrement count loop
13511 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
13512 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13513 0<> WHILE \ ----> out of loop ----+
13514 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
13516 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
13517 CMP Y,X \ 1 | cycle time out of bound ?
13518 U>= IF \ 2 ^ | yes:
13519 BIC #$30,&RC5_TIM_CTL \ | | stop timer
13520 GOTO FW1 \ | | quit on truncated RC5 message
13522 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
13524 REPEAT \ ----> loop back --+ | with X = new RC5_period value
13525 \ ******************************\ |
13526 \ RC5_SampleEndOf: \ <---------------------+
13527 \ ******************************\
13528 BIC #$30,&RC5_TIM_CTL \ stop timer
13529 \ ******************************\
13530 \ RC5_ComputeNewRC5word \
13531 \ ******************************\
13532 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
13533 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
13534 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
13535 \ ******************************\
13536 \ RC5_ComputeC6bit \
13537 \ ******************************\
13538 BIT #BIT14,T \ test /C6 bit in T
13539 0= IF BIS #BIT6,X \ set C6 bit in X
13540 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
13541 \ ******************************\
13542 \ RC5_CommandByteIsDone \ -- BASE RC5_code
13543 \ ******************************\
13544 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
13545 \ ******************************\
13546 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
13547 XOR @RSP,T \ (new XOR old) Toggle bits
13548 BIT #UF10,T \ repeated RC5_command ?
13549 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
13550 XOR #UF10,0(RSP) \ 5 toggle bit memory
13551 \ ******************************\
13552 \ Display IR_RC5 code \
13553 \ ******************************\
13554 SUB #8,PSP \ TOS -- x x x x TOS
13555 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
13556 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
13557 MOV #$10,&BASEADR \ set hexadecimal base
13558 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
13559 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
13560 LO2HI \ switch from assembler to FORTH
13561 LCD_CLEAR \ set LCD cursor at home
13562 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
13563 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
13564 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
13565 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
13566 HI2LO \ -- switch from FORTH to assembler
13567 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
13568 MOV @PSP+,TOS \ -- TOS
13570 MOV @RSP+,SR \ restore SR flags
13571 BIC #%1111_1000,SR \ but force CPU Active Mode
13572 RET \ (instead of RETI)
13576 \ ------------------------------\
13577 HDNCODE STOP_R2L \ define new STOP_APP
13578 \ ------------------------------\
13579 CMP #RET_ADR,&{RC5TOLCD}+8 \
13580 0<> IF \ if previous START executing
13581 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
13582 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
13583 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
13584 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
13585 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
13586 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
13587 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
13588 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
13589 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
13590 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
13595 \ ------------------------------\
13597 \ ------------------------------\
13598 BW1 \ <-- INI_R2L for some events
13600 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
13602 ." RC5toLCD is removed,"
13603 ." type START to restart"
13606 \ ------------------------------\
13608 \ ------------------------------\
13609 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
13610 \ ------------------------------\
13612 \ ------------------------------\
13613 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
13614 \ ------------------------------\
13615 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
13616 \ ------------------------------\
13617 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
13618 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
13620 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
13621 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
13623 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
13624 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
13625 \ CMP #4,TOS \ hardware RST
13626 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
13627 \ CMP #2,TOS \ Power_ON event
13628 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13630 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13632 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13634 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13635 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
13636 \ ------------------------------\
13637 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
13638 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13639 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13640 \ -- \ID input divider \ 10 = /4
13641 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
13642 \ - \TBCLR TimerB Clear
13645 \ -------------------------------\
13646 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13647 \ -- \CM Capture Mode
13652 \ --- \OUTMOD \ 011 = set/reset
13658 \ -------------------------------\
13660 \ -------------------------------\
13662 \ ------------------------------\
13663 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13664 \ ------------------------------\
13665 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13666 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13667 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
13668 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13670 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
13671 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13673 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
13674 \ ------------------------------\
13675 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13676 \ ------------------------------\
13677 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
13678 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13679 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13680 \ ------------------------------\
13681 BIS.B #LCDVo,&LCDVo_DIR \
13682 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
13683 \ ------------------------------\
13684 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13685 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13686 \ ------------------------------\
13687 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13688 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13689 \ ******************************\
13691 \ ******************************\
13692 BIS.B #RC5,&IR_IE \ enable RC5_Int
13693 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13694 \ ******************************\
13695 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13696 \ ******************************\
13697 \ %01 0001 0100 \ TAxCTL
13698 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
13699 \ -- \ ID divided by 1
13700 \ -- \ MC MODE = up to TAxCCRn
13701 \ - \ TACLR clear timer count
13704 \ ------------------------------\
13705 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
13706 \ ------------------------------\
13708 \ --- \ TAIDEX pre divisor
13709 \ ------------------------------\
13710 \ %0000 0000 0000 0101 \ TAxCCR0
13711 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13712 \ ------------------------------\
13713 \ %0000 0000 0001 0000 \ TAxCCTL0
13714 \ - \ CAP capture/compare mode = compare
13717 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
13718 \ ------------------------------\
13719 \ define LPM mode for ACCEPT \
13720 \ ------------------------------\
13721 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
13722 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13723 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13724 \ ------------------------------\
13726 \ ------------------------------\
13728 \ ------------------------------\
13729 #1000 20_US \ 1- wait 20 ms
13730 %011 TOP_LCD \ 2- send DB5=DB4=1
13731 #205 20_US \ 3- wait 4,1 ms
13732 %011 TOP_LCD \ 4- send again DB5=DB4=1
13733 #5 20_US \ 5- wait 0,1 ms
13734 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13735 #2 20_US \ wait 40 us = LCD cycle
13736 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13737 #2 20_US \ wait 40 us = LCD cycle
13738 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13739 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13740 LCD_CLEAR \ 10- "LCD_Clear"
13741 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13742 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13743 LCD_CLEAR \ 10- "LCD_Clear"
13744 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13745 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13746 CR ." I love you" \ display message on LCD
13747 ['] CR >BODY IS CR \ CR executes its default value
13748 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13749 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13752 \ ------------------------------\
13754 \ ------------------------------\
13755 CODE START \ this routine replaces WARM and COLD default values by these of this application.
13756 \ ------------------------------\
13757 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
13758 0= IF \ if not done, customizes MARKER_DOES
13759 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
13760 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
13761 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
13762 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
13763 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13764 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
13765 MOV #RC5_INT,&IR_VEC \ init interrupt vector
13766 MOV #INI_R2L,PC \ then execute new INI_APP, without return
13770 \ ------------------------------\
13773 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13775 MARKER {RC5TOLCD} \ restore the state before MARKER definition
13776 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
13777 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
13778 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
13779 \ {RC5TOLCD}+14: make room to save previous IR_VEC
13781 [UNDEFINED] CONSTANT [IF]
13782 \ https://forth-standard.org/standard/core/CONSTANT
13783 \ CONSTANT <name> n -- define a Forth CONSTANT
13787 MOV TOS,-2(W) \ PFA = n
13794 [UNDEFINED] STATE [IF]
13795 \ https://forth-standard.org/standard/core/STATE
13796 \ STATE -- a-addr holds compiler state
13797 STATEADR CONSTANT STATE
13801 \ https://forth-standard.org/standard/core/Equal
13802 \ = x1 x2 -- flag test x1=x2
13809 XOR #-1,TOS \ 1 flag Z = 1
13814 [UNDEFINED] IF [IF] \ define IF and THEN
13815 \ https://forth-standard.org/standard/core/IF
13816 \ IF -- IFadr initialize conditional forward branch
13817 CODE IF \ immediate
13820 MOV &DP,TOS \ -- HERE
13821 ADD #4,&DP \ compile one word, reserve one word
13822 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
13823 ADD #2,TOS \ -- HERE+2=IFadr
13827 \ https://forth-standard.org/standard/core/THEN
13828 \ THEN IFadr -- resolve forward branch
13829 CODE THEN \ immediate
13830 MOV &DP,0(TOS) \ -- IFadr
13836 [UNDEFINED] ELSE [IF]
13837 \ https://forth-standard.org/standard/core/ELSE
13838 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
13839 CODE ELSE \ immediate
13840 ADD #4,&DP \ make room to compile two words
13841 MOV &DP,W \ W=HERE+4
13843 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
13845 MOV W,TOS \ -- ELSEadr
13850 [UNDEFINED] IS [IF] \ define DEFER! and IS
13852 \ https://forth-standard.org/standard/core/DEFERStore
13853 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
13854 CODE DEFER! \ xt2 xt1 --
13855 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
13860 \ https://forth-standard.org/standard/core/IS
13863 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
13864 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
13865 \ or in a definition : ... ['] U. IS DISPLAY ...
13866 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
13868 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
13872 IF POSTPONE ['] POSTPONE DEFER!
13878 [UNDEFINED] >BODY [IF]
13879 \ https://forth-standard.org/standard/core/toBODY
13880 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
13887 \ CODE 20uS \ n -- 8MHz version
13888 \ BEGIN \ 4 + 16 ~ loop
13889 \ MOV #39,rDOCON \ 39
13896 \ MOV #XDOCON,rDOCON \ 2
13901 CODE 20_US \ n -- n * 20 us
13902 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13904 BIT #1,&LCD_TIM_CTL \ 3
13905 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13906 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13908 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13913 CODE TOP_LCD \ LCD Sample
13914 \ \ if write : %xxxx_WWWW --
13915 \ \ if read : -- %0000_RRRR
13916 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13917 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13918 0= IF \ write LCD bits pattern
13919 AND.B #LCD_DB,TOS \
13920 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13921 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13924 THEN \ read LCD bits pattern
13927 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13928 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13929 AND.B #LCD_DB,TOS \
13933 CODE LCD_WRC \ char -- Write Char
13934 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13936 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
13937 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
13938 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13939 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13940 COLON \ high level word starts here
13941 TOP_LCD 2 20_US \ write high nibble first
13945 CODE LCD_WRF \ func -- Write Fonction
13946 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13950 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13951 : LCD_HOME $02 LCD_WRF 100 20_us ;
13953 \ [UNDEFINED] OR [IF]
13955 \ \ https://forth-standard.org/standard/core/OR
13956 \ \ C OR x1 x2 -- x3 logical OR
13964 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
13965 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
13966 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
13967 \ : LCD_FN_SET $20 OR LCD_WrF ;
13968 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
13969 \ : LCD_GOTO $80 OR LCD_WrF ;
13972 \ CODE LCD_RDS \ -- status Read Status
13973 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13974 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13975 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13976 \ COLON \ starts a FORTH word
13977 \ TOP_LCD 2 20_us \ -- %0000_HHHH
13978 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
13979 \ HI2LO \ switch from FORTH to assembler
13980 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
13981 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
13982 \ MOV @RSP+,IP \ restore IP saved by COLON
13986 \ CODE LCD_RDC \ -- char Read Char
13987 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13992 \ ******************************\
13993 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13994 \ ******************************\
13995 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
13996 BIT.B #SW2,&SW2_IN \ test switch S2
13997 0= IF \ case of switch S2 pressed
13998 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14000 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
14003 BIT.B #SW1,&SW1_IN \ test switch S1 input
14004 0= IF \ case of Switch S1 pressed
14005 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14007 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14014 \ ******************************\
14015 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
14016 \ ******************************\
14017 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14018 \ ******************************\
14019 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14020 \ \ SMclock = 8|16|24 MHz
14021 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14022 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14023 \ \ SR(9)=new Toggle bit memory (ADD on)
14024 \ ******************************\
14025 \ RC5_FirstStartBitHalfCycle: \
14026 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14027 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
14028 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
14030 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
14031 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
14033 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
14034 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
14036 MOV #1778,X \ RC5_Period * 1us
14037 MOV #14,W \ count of loop
14039 \ ******************************\
14040 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14041 \ ******************************\ |
14042 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14043 \ RC5_Compute_3/4_Period: \ |
14044 RRUM #1,X \ X=1/2 cycle |
14047 ADD X,Y \ Y=3/4 cycle
14048 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14050 \ ******************************\
14051 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14052 \ ******************************\
14053 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14054 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14055 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14056 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14057 SUB #1,W \ decrement count loop
14058 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14059 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14060 0<> WHILE \ ----> out of loop ----+
14061 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14063 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14064 CMP Y,X \ 1 | cycle time out of bound ?
14065 U>= IF \ 2 ^ | yes:
14066 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14067 GOTO FW1 \ | | quit on truncated RC5 message
14069 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14071 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14072 \ ******************************\ |
14073 \ RC5_SampleEndOf: \ <---------------------+
14074 \ ******************************\
14075 BIC #$30,&RC5_TIM_CTL \ stop timer
14076 \ ******************************\
14077 \ RC5_ComputeNewRC5word \
14078 \ ******************************\
14079 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14080 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14081 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14082 \ ******************************\
14083 \ RC5_ComputeC6bit \
14084 \ ******************************\
14085 BIT #BIT14,T \ test /C6 bit in T
14086 0= IF BIS #BIT6,X \ set C6 bit in X
14087 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14088 \ ******************************\
14089 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14090 \ ******************************\
14091 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
14092 \ ******************************\
14093 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14094 XOR @RSP,T \ (new XOR old) Toggle bits
14095 BIT #UF10,T \ repeated RC5_command ?
14096 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
14097 XOR #UF10,0(RSP) \ 5 toggle bit memory
14098 \ ******************************\
14099 \ Display IR_RC5 code \
14100 \ ******************************\
14101 SUB #8,PSP \ TOS -- x x x x TOS
14102 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14103 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14104 MOV #$10,&BASEADR \ set hexadecimal base
14105 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14106 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14107 LO2HI \ switch from assembler to FORTH
14108 LCD_CLEAR \ set LCD cursor at home
14109 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14110 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14111 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14112 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14113 HI2LO \ -- switch from FORTH to assembler
14114 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14115 MOV @PSP+,TOS \ -- TOS
14117 MOV @RSP+,SR \ restore SR flags
14118 BIC #%1111_1000,SR \ but force CPU Active Mode
14119 RET \ (instead of RETI)
14123 \ ------------------------------\
14124 HDNCODE STOP_R2L \ define new STOP_APP
14125 \ ------------------------------\
14126 CMP #RET_ADR,&{RC5TOLCD}+8 \
14127 0<> IF \ if previous START executing
14128 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
14129 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
14130 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
14131 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
14132 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
14133 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
14134 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
14135 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
14136 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
14137 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
14142 \ ------------------------------\
14144 \ ------------------------------\
14145 BW1 \ <-- INI_R2L for some events
14147 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
14149 ." RC5toLCD is removed,"
14150 ." type START to restart"
14153 \ ------------------------------\
14155 \ ------------------------------\
14156 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
14157 \ ------------------------------\
14159 \ ------------------------------\
14160 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
14161 \ ------------------------------\
14162 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
14163 \ ------------------------------\
14164 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
14165 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
14167 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
14168 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
14170 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
14171 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
14172 \ CMP #4,TOS \ hardware RST
14173 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
14174 \ CMP #2,TOS \ Power_ON event
14175 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
14177 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
14179 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
14181 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
14182 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
14183 \ ------------------------------\
14184 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
14185 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14186 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14187 \ -- \ID input divider \ 10 = /4
14188 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14189 \ - \TBCLR TimerB Clear
14192 \ -------------------------------\
14193 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14194 \ -- \CM Capture Mode
14199 \ --- \OUTMOD \ 011 = set/reset
14205 \ -------------------------------\
14207 \ -------------------------------\
14209 \ ------------------------------\
14210 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14211 \ ------------------------------\
14212 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14213 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14214 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
14215 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14217 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
14218 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14220 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
14221 \ ------------------------------\
14222 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14223 \ ------------------------------\
14224 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
14225 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14226 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14227 \ ------------------------------\
14228 BIS.B #LCDVo,&LCDVo_DIR \
14229 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
14230 \ ------------------------------\
14231 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14232 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14233 \ ------------------------------\
14234 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14235 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14236 \ ******************************\
14238 \ ******************************\
14239 BIS.B #RC5,&IR_IE \ enable RC5_Int
14240 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14241 \ ******************************\
14242 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14243 \ ******************************\
14244 \ %01 0001 0100 \ TAxCTL
14245 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
14246 \ -- \ ID divided by 1
14247 \ -- \ MC MODE = up to TAxCCRn
14248 \ - \ TACLR clear timer count
14251 \ ------------------------------\
14252 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
14253 \ ------------------------------\
14255 \ --- \ TAIDEX pre divisor
14256 \ ------------------------------\
14257 \ %0000 0000 0000 0101 \ TAxCCR0
14258 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14259 \ ------------------------------\
14260 \ %0000 0000 0001 0000 \ TAxCCTL0
14261 \ - \ CAP capture/compare mode = compare
14264 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
14265 \ ------------------------------\
14266 \ define LPM mode for ACCEPT \
14267 \ ------------------------------\
14268 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
14269 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14270 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14271 \ ------------------------------\
14273 \ ------------------------------\
14275 \ ------------------------------\
14276 #1000 20_US \ 1- wait 20 ms
14277 %011 TOP_LCD \ 2- send DB5=DB4=1
14278 #205 20_US \ 3- wait 4,1 ms
14279 %011 TOP_LCD \ 4- send again DB5=DB4=1
14280 #5 20_US \ 5- wait 0,1 ms
14281 %011 TOP_LCD \ 6- send again again DB5=DB4=1
14282 #2 20_US \ wait 40 us = LCD cycle
14283 %010 TOP_LCD \ 7- send DB5=1 DB4=0
14284 #2 20_US \ wait 40 us = LCD cycle
14285 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14286 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14287 LCD_CLEAR \ 10- "LCD_Clear"
14288 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14289 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14290 LCD_CLEAR \ 10- "LCD_Clear"
14291 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14292 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14293 CR ." I love you" \ display message on LCD
14294 ['] CR >BODY IS CR \ CR executes its default value
14295 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
14296 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14299 \ ------------------------------\
14301 \ ------------------------------\
14302 CODE START \ this routine replaces WARM and COLD default values by these of this application.
14303 \ ------------------------------\
14304 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
14305 0= IF \ if not done, customizes MARKER_DOES
14306 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
14307 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
14308 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
14309 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
14310 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14311 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
14312 MOV #RC5_INT,&IR_VEC \ init interrupt vector
14313 MOV #INI_R2L,PC \ then execute new INI_APP, without return
14317 \ ------------------------------\
14320 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
14322 MARKER {RC5TOLCD} \ restore the state before MARKER definition
14323 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
14324 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
14325 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
14326 \ {RC5TOLCD}+14: make room to save previous IR_VEC
14328 [UNDEFINED] CONSTANT [IF]
14329 \ https://forth-standard.org/standard/core/CONSTANT
14330 \ CONSTANT <name> n -- define a Forth CONSTANT
14334 MOV TOS,-2(W) \ PFA = n
14341 [UNDEFINED] STATE [IF]
14342 \ https://forth-standard.org/standard/core/STATE
14343 \ STATE -- a-addr holds compiler state
14344 STATEADR CONSTANT STATE
14348 \ https://forth-standard.org/standard/core/Equal
14349 \ = x1 x2 -- flag test x1=x2
14356 XOR #-1,TOS \ 1 flag Z = 1
14361 [UNDEFINED] IF [IF] \ define IF and THEN
14362 \ https://forth-standard.org/standard/core/IF
14363 \ IF -- IFadr initialize conditional forward branch
14364 CODE IF \ immediate
14367 MOV &DP,TOS \ -- HERE
14368 ADD #4,&DP \ compile one word, reserve one word
14369 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
14370 ADD #2,TOS \ -- HERE+2=IFadr
14374 \ https://forth-standard.org/standard/core/THEN
14375 \ THEN IFadr -- resolve forward branch
14376 CODE THEN \ immediate
14377 MOV &DP,0(TOS) \ -- IFadr
14383 [UNDEFINED] ELSE [IF]
14384 \ https://forth-standard.org/standard/core/ELSE
14385 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
14386 CODE ELSE \ immediate
14387 ADD #4,&DP \ make room to compile two words
14388 MOV &DP,W \ W=HERE+4
14390 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
14392 MOV W,TOS \ -- ELSEadr
14397 [UNDEFINED] IS [IF] \ define DEFER! and IS
14399 \ https://forth-standard.org/standard/core/DEFERStore
14400 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
14401 CODE DEFER! \ xt2 xt1 --
14402 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
14407 \ https://forth-standard.org/standard/core/IS
14410 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
14411 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
14412 \ or in a definition : ... ['] U. IS DISPLAY ...
14413 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
14415 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
14419 IF POSTPONE ['] POSTPONE DEFER!
14425 [UNDEFINED] >BODY [IF]
14426 \ https://forth-standard.org/standard/core/toBODY
14427 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
14434 \ CODE 20uS \ n -- 8MHz version
14435 \ BEGIN \ 4 + 16 ~ loop
14436 \ MOV #39,rDOCON \ 39
14443 \ MOV #XDOCON,rDOCON \ 2
14448 CODE 20_US \ n -- n * 20 us
14449 BEGIN \ here we presume that LCD_TIM_IFG = 1...
14451 BIT #1,&LCD_TIM_CTL \ 3
14452 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
14453 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
14455 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
14460 CODE TOP_LCD \ LCD Sample
14461 \ \ if write : %xxxx_WWWW --
14462 \ \ if read : -- %0000_RRRR
14463 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14464 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14465 0= IF \ write LCD bits pattern
14466 AND.B #LCD_DB,TOS \
14467 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14468 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14471 THEN \ read LCD bits pattern
14474 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14475 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14476 AND.B #LCD_DB,TOS \
14480 CODE LCD_WRC \ char -- Write Char
14481 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14483 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
14484 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
14485 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14486 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14487 COLON \ high level word starts here
14488 TOP_LCD 2 20_US \ write high nibble first
14492 CODE LCD_WRF \ func -- Write Fonction
14493 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14497 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
14498 : LCD_HOME $02 LCD_WRF 100 20_us ;
14500 \ [UNDEFINED] OR [IF]
14502 \ \ https://forth-standard.org/standard/core/OR
14503 \ \ C OR x1 x2 -- x3 logical OR
14511 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
14512 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
14513 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
14514 \ : LCD_FN_SET $20 OR LCD_WrF ;
14515 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
14516 \ : LCD_GOTO $80 OR LCD_WrF ;
14519 \ CODE LCD_RDS \ -- status Read Status
14520 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14521 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14522 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14523 \ COLON \ starts a FORTH word
14524 \ TOP_LCD 2 20_us \ -- %0000_HHHH
14525 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
14526 \ HI2LO \ switch from FORTH to assembler
14527 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
14528 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
14529 \ MOV @RSP+,IP \ restore IP saved by COLON
14533 \ CODE LCD_RDC \ -- char Read Char
14534 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14539 \ ******************************\
14540 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14541 \ ******************************\
14542 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
14543 BIT.B #SW2,&SW2_IN \ test switch S2
14544 0= IF \ case of switch S2 pressed
14545 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14547 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
14550 BIT.B #SW1,&SW1_IN \ test switch S1 input
14551 0= IF \ case of Switch S1 pressed
14552 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14554 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14561 \ ******************************\
14562 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
14563 \ ******************************\
14564 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14565 \ ******************************\
14566 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14567 \ \ SMclock = 8|16|24 MHz
14568 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14569 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14570 \ \ SR(9)=new Toggle bit memory (ADD on)
14571 \ ******************************\
14572 \ RC5_FirstStartBitHalfCycle: \
14573 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14574 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
14575 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
14577 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
14578 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
14580 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
14581 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
14583 MOV #1778,X \ RC5_Period * 1us
14584 MOV #14,W \ count of loop
14586 \ ******************************\
14587 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14588 \ ******************************\ |
14589 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14590 \ RC5_Compute_3/4_Period: \ |
14591 RRUM #1,X \ X=1/2 cycle |
14594 ADD X,Y \ Y=3/4 cycle
14595 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14597 \ ******************************\
14598 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14599 \ ******************************\
14600 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14601 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14602 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14603 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14604 SUB #1,W \ decrement count loop
14605 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14606 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14607 0<> WHILE \ ----> out of loop ----+
14608 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14610 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14611 CMP Y,X \ 1 | cycle time out of bound ?
14612 U>= IF \ 2 ^ | yes:
14613 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14614 GOTO FW1 \ | | quit on truncated RC5 message
14616 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14618 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14619 \ ******************************\ |
14620 \ RC5_SampleEndOf: \ <---------------------+
14621 \ ******************************\
14622 BIC #$30,&RC5_TIM_CTL \ stop timer
14623 \ ******************************\
14624 \ RC5_ComputeNewRC5word \
14625 \ ******************************\
14626 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14627 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14628 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14629 \ ******************************\
14630 \ RC5_ComputeC6bit \
14631 \ ******************************\
14632 BIT #BIT14,T \ test /C6 bit in T
14633 0= IF BIS #BIT6,X \ set C6 bit in X
14634 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14635 \ ******************************\
14636 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14637 \ ******************************\
14638 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
14639 \ ******************************\
14640 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14641 XOR @RSP,T \ (new XOR old) Toggle bits
14642 BIT #UF10,T \ repeated RC5_command ?
14643 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
14644 XOR #UF10,0(RSP) \ 5 toggle bit memory
14645 \ ******************************\
14646 \ Display IR_RC5 code \
14647 \ ******************************\
14648 SUB #8,PSP \ TOS -- x x x x TOS
14649 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14650 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14651 MOV #$10,&BASEADR \ set hexadecimal base
14652 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14653 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14654 LO2HI \ switch from assembler to FORTH
14655 LCD_CLEAR \ set LCD cursor at home
14656 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14657 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14658 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14659 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14660 HI2LO \ -- switch from FORTH to assembler
14661 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14662 MOV @PSP+,TOS \ -- TOS
14664 MOV @RSP+,SR \ restore SR flags
14665 BIC #%1111_1000,SR \ but force CPU Active Mode
14666 RET \ (instead of RETI)
14670 \ ------------------------------\
14671 HDNCODE STOP_R2L \ define new STOP_APP
14672 \ ------------------------------\
14673 CMP #RET_ADR,&{RC5TOLCD}+8 \
14674 0<> IF \ if previous START executing
14675 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
14676 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
14677 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
14678 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
14679 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
14680 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
14681 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
14682 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
14683 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
14684 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
14689 \ ------------------------------\
14691 \ ------------------------------\
14692 BW1 \ <-- INI_R2L for some events
14694 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
14696 ." RC5toLCD is removed,"
14697 ." type START to restart"
14700 \ ------------------------------\
14702 \ ------------------------------\
14703 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
14704 \ ------------------------------\
14706 \ ------------------------------\
14707 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
14708 \ ------------------------------\
14709 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
14710 \ ------------------------------\
14711 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
14712 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
14714 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
14715 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
14717 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
14718 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
14719 \ CMP #4,TOS \ hardware RST
14720 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
14721 \ CMP #2,TOS \ Power_ON event
14722 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
14724 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
14726 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
14728 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
14729 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
14730 \ ------------------------------\
14731 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
14732 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14733 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14734 \ -- \ID input divider \ 10 = /4
14735 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14736 \ - \TBCLR TimerB Clear
14739 \ -------------------------------\
14740 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14741 \ -- \CM Capture Mode
14746 \ --- \OUTMOD \ 011 = set/reset
14752 \ -------------------------------\
14754 \ -------------------------------\
14756 \ ------------------------------\
14757 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14758 \ ------------------------------\
14759 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14760 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14761 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
14762 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14764 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
14765 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14767 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
14768 \ ------------------------------\
14769 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14770 \ ------------------------------\
14771 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
14772 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14773 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14774 \ ------------------------------\
14775 BIS.B #LCDVo,&LCDVo_DIR \
14776 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
14777 \ ------------------------------\
14778 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14779 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14780 \ ------------------------------\
14781 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14782 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14783 \ ******************************\
14785 \ ******************************\
14786 BIS.B #RC5,&IR_IE \ enable RC5_Int
14787 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14788 \ ******************************\
14789 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14790 \ ******************************\
14791 \ %01 0001 0100 \ TAxCTL
14792 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
14793 \ -- \ ID divided by 1
14794 \ -- \ MC MODE = up to TAxCCRn
14795 \ - \ TACLR clear timer count
14798 \ ------------------------------\
14799 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
14800 \ ------------------------------\
14802 \ --- \ TAIDEX pre divisor
14803 \ ------------------------------\
14804 \ %0000 0000 0000 0101 \ TAxCCR0
14805 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14806 \ ------------------------------\
14807 \ %0000 0000 0001 0000 \ TAxCCTL0
14808 \ - \ CAP capture/compare mode = compare
14811 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
14812 \ ------------------------------\
14813 \ define LPM mode for ACCEPT \
14814 \ ------------------------------\
14815 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
14816 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14817 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14818 \ ------------------------------\
14820 \ ------------------------------\
14822 \ ------------------------------\
14823 #1000 20_US \ 1- wait 20 ms
14824 %011 TOP_LCD \ 2- send DB5=DB4=1
14825 #205 20_US \ 3- wait 4,1 ms
14826 %011 TOP_LCD \ 4- send again DB5=DB4=1
14827 #5 20_US \ 5- wait 0,1 ms
14828 %011 TOP_LCD \ 6- send again again DB5=DB4=1
14829 #2 20_US \ wait 40 us = LCD cycle
14830 %010 TOP_LCD \ 7- send DB5=1 DB4=0
14831 #2 20_US \ wait 40 us = LCD cycle
14832 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14833 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14834 LCD_CLEAR \ 10- "LCD_Clear"
14835 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14836 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14837 LCD_CLEAR \ 10- "LCD_Clear"
14838 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14839 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14840 CR ." I love you" \ display message on LCD
14841 ['] CR >BODY IS CR \ CR executes its default value
14842 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
14843 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14846 \ ------------------------------\
14848 \ ------------------------------\
14849 CODE START \ this routine replaces WARM and COLD default values by these of this application.
14850 \ ------------------------------\
14851 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
14852 0= IF \ if not done, customizes MARKER_DOES
14853 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
14854 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
14855 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
14856 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
14857 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14858 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
14859 MOV #RC5_INT,&IR_VEC \ init interrupt vector
14860 MOV #INI_R2L,PC \ then execute new INI_APP, without return
14864 \ ------------------------------\
14867 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
14869 MARKER {RC5TOLCD} \ restore the state before MARKER definition
14870 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
14871 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
14872 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
14873 \ {RC5TOLCD}+14: make room to save previous IR_VEC
14875 [UNDEFINED] CONSTANT [IF]
14876 \ https://forth-standard.org/standard/core/CONSTANT
14877 \ CONSTANT <name> n -- define a Forth CONSTANT
14881 MOV TOS,-2(W) \ PFA = n
14888 [UNDEFINED] STATE [IF]
14889 \ https://forth-standard.org/standard/core/STATE
14890 \ STATE -- a-addr holds compiler state
14891 STATEADR CONSTANT STATE
14895 \ https://forth-standard.org/standard/core/Equal
14896 \ = x1 x2 -- flag test x1=x2
14903 XOR #-1,TOS \ 1 flag Z = 1
14908 [UNDEFINED] IF [IF] \ define IF and THEN
14909 \ https://forth-standard.org/standard/core/IF
14910 \ IF -- IFadr initialize conditional forward branch
14911 CODE IF \ immediate
14914 MOV &DP,TOS \ -- HERE
14915 ADD #4,&DP \ compile one word, reserve one word
14916 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
14917 ADD #2,TOS \ -- HERE+2=IFadr
14921 \ https://forth-standard.org/standard/core/THEN
14922 \ THEN IFadr -- resolve forward branch
14923 CODE THEN \ immediate
14924 MOV &DP,0(TOS) \ -- IFadr
14930 [UNDEFINED] ELSE [IF]
14931 \ https://forth-standard.org/standard/core/ELSE
14932 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
14933 CODE ELSE \ immediate
14934 ADD #4,&DP \ make room to compile two words
14935 MOV &DP,W \ W=HERE+4
14937 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
14939 MOV W,TOS \ -- ELSEadr
14944 [UNDEFINED] IS [IF] \ define DEFER! and IS
14946 \ https://forth-standard.org/standard/core/DEFERStore
14947 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
14948 CODE DEFER! \ xt2 xt1 --
14949 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
14954 \ https://forth-standard.org/standard/core/IS
14957 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
14958 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
14959 \ or in a definition : ... ['] U. IS DISPLAY ...
14960 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
14962 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
14966 IF POSTPONE ['] POSTPONE DEFER!
14972 [UNDEFINED] >BODY [IF]
14973 \ https://forth-standard.org/standard/core/toBODY
14974 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
14981 \ CODE 20uS \ n -- 8MHz version
14982 \ BEGIN \ 4 + 16 ~ loop
14983 \ MOV #39,rDOCON \ 39
14990 \ MOV #XDOCON,rDOCON \ 2
14995 CODE 20_US \ n -- n * 20 us
14996 BEGIN \ here we presume that LCD_TIM_IFG = 1...
14998 BIT #1,&LCD_TIM_CTL \ 3
14999 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15000 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15002 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15007 CODE TOP_LCD \ LCD Sample
15008 \ \ if write : %xxxx_WWWW --
15009 \ \ if read : -- %0000_RRRR
15010 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15011 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15012 0= IF \ write LCD bits pattern
15013 AND.B #LCD_DB,TOS \
15014 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15015 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15018 THEN \ read LCD bits pattern
15021 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15022 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15023 AND.B #LCD_DB,TOS \
15027 CODE LCD_WRC \ char -- Write Char
15028 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15030 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
15031 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
15032 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15033 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15034 COLON \ high level word starts here
15035 TOP_LCD 2 20_US \ write high nibble first
15039 CODE LCD_WRF \ func -- Write Fonction
15040 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15044 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
15045 : LCD_HOME $02 LCD_WRF 100 20_us ;
15047 \ [UNDEFINED] OR [IF]
15049 \ \ https://forth-standard.org/standard/core/OR
15050 \ \ C OR x1 x2 -- x3 logical OR
15058 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
15059 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
15060 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
15061 \ : LCD_FN_SET $20 OR LCD_WrF ;
15062 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
15063 \ : LCD_GOTO $80 OR LCD_WrF ;
15066 \ CODE LCD_RDS \ -- status Read Status
15067 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15068 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15069 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15070 \ COLON \ starts a FORTH word
15071 \ TOP_LCD 2 20_us \ -- %0000_HHHH
15072 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
15073 \ HI2LO \ switch from FORTH to assembler
15074 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
15075 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
15076 \ MOV @RSP+,IP \ restore IP saved by COLON
15080 \ CODE LCD_RDC \ -- char Read Char
15081 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15086 \ ******************************\
15087 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15088 \ ******************************\
15089 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
15090 BIT.B #SW2,&SW2_IN \ test switch S2
15091 0= IF \ case of switch S2 pressed
15092 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15094 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
15097 BIT.B #SW1,&SW1_IN \ test switch S1 input
15098 0= IF \ case of Switch S1 pressed
15099 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15101 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15108 \ ******************************\
15109 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
15110 \ ******************************\
15111 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15112 \ ******************************\
15113 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15114 \ \ SMclock = 8|16|24 MHz
15115 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15116 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15117 \ \ SR(9)=new Toggle bit memory (ADD on)
15118 \ ******************************\
15119 \ RC5_FirstStartBitHalfCycle: \
15120 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15121 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
15122 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
15124 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
15125 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
15127 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
15128 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
15130 MOV #1778,X \ RC5_Period * 1us
15131 MOV #14,W \ count of loop
15133 \ ******************************\
15134 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
15135 \ ******************************\ |
15136 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15137 \ RC5_Compute_3/4_Period: \ |
15138 RRUM #1,X \ X=1/2 cycle |
15141 ADD X,Y \ Y=3/4 cycle
15142 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
15144 \ ******************************\
15145 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15146 \ ******************************\
15147 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15148 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
15149 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15150 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15151 SUB #1,W \ decrement count loop
15152 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
15153 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15154 0<> WHILE \ ----> out of loop ----+
15155 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15157 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
15158 CMP Y,X \ 1 | cycle time out of bound ?
15159 U>= IF \ 2 ^ | yes:
15160 BIC #$30,&RC5_TIM_CTL \ | | stop timer
15161 GOTO FW1 \ | | quit on truncated RC5 message
15163 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
15165 REPEAT \ ----> loop back --+ | with X = new RC5_period value
15166 \ ******************************\ |
15167 \ RC5_SampleEndOf: \ <---------------------+
15168 \ ******************************\
15169 BIC #$30,&RC5_TIM_CTL \ stop timer
15170 \ ******************************\
15171 \ RC5_ComputeNewRC5word \
15172 \ ******************************\
15173 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
15174 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
15175 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
15176 \ ******************************\
15177 \ RC5_ComputeC6bit \
15178 \ ******************************\
15179 BIT #BIT14,T \ test /C6 bit in T
15180 0= IF BIS #BIT6,X \ set C6 bit in X
15181 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
15182 \ ******************************\
15183 \ RC5_CommandByteIsDone \ -- BASE RC5_code
15184 \ ******************************\
15185 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
15186 \ ******************************\
15187 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
15188 XOR @RSP,T \ (new XOR old) Toggle bits
15189 BIT #UF10,T \ repeated RC5_command ?
15190 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
15191 XOR #UF10,0(RSP) \ 5 toggle bit memory
15192 \ ******************************\
15193 \ Display IR_RC5 code \
15194 \ ******************************\
15195 SUB #8,PSP \ TOS -- x x x x TOS
15196 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
15197 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
15198 MOV #$10,&BASEADR \ set hexadecimal base
15199 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
15200 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
15201 LO2HI \ switch from assembler to FORTH
15202 LCD_CLEAR \ set LCD cursor at home
15203 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
15204 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
15205 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
15206 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
15207 HI2LO \ -- switch from FORTH to assembler
15208 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
15209 MOV @PSP+,TOS \ -- TOS
15211 MOV @RSP+,SR \ restore SR flags
15212 BIC #%1111_1000,SR \ but force CPU Active Mode
15213 RET \ (instead of RETI)
15217 \ ------------------------------\
15218 HDNCODE STOP_R2L \ define new STOP_APP
15219 \ ------------------------------\
15220 CMP #RET_ADR,&{RC5TOLCD}+8 \
15221 0<> IF \ if previous START executing
15222 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
15223 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
15224 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
15225 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
15226 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
15227 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
15228 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
15229 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
15230 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
15231 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
15236 \ ------------------------------\
15238 \ ------------------------------\
15239 BW1 \ <-- INI_R2L for some events
15241 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15243 ." RC5toLCD is removed,"
15244 ." type START to restart"
15247 \ ------------------------------\
15249 \ ------------------------------\
15250 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
15251 \ ------------------------------\
15253 \ ------------------------------\
15254 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
15255 \ ------------------------------\
15256 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
15257 \ ------------------------------\
15258 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
15259 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
15261 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
15262 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
15264 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
15265 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
15266 \ CMP #4,TOS \ hardware RST
15267 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
15268 \ CMP #2,TOS \ Power_ON event
15269 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
15271 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
15273 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
15275 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
15276 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
15277 \ ------------------------------\
15278 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15279 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15280 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15281 \ -- \ID input divider \ 10 = /4
15282 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15283 \ - \TBCLR TimerB Clear
15286 \ -------------------------------\
15287 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15288 \ -- \CM Capture Mode
15293 \ --- \OUTMOD \ 011 = set/reset
15299 \ -------------------------------\
15301 \ -------------------------------\
15303 \ ------------------------------\
15304 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15305 \ ------------------------------\
15306 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15307 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15308 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
15309 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15311 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
15312 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15314 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
15315 \ ------------------------------\
15316 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15317 \ ------------------------------\
15318 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
15319 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15320 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15321 \ ------------------------------\
15322 BIS.B #LCDVo,&LCDVo_DIR \
15323 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
15324 \ ------------------------------\
15325 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15326 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15327 \ ------------------------------\
15328 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15329 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15330 \ ******************************\
15332 \ ******************************\
15333 BIS.B #RC5,&IR_IE \ enable RC5_Int
15334 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15335 \ ******************************\
15336 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15337 \ ******************************\
15338 \ %01 0001 0100 \ TAxCTL
15339 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
15340 \ -- \ ID divided by 1
15341 \ -- \ MC MODE = up to TAxCCRn
15342 \ - \ TACLR clear timer count
15345 \ ------------------------------\
15346 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
15347 \ ------------------------------\
15349 \ --- \ TAIDEX pre divisor
15350 \ ------------------------------\
15351 \ %0000 0000 0000 0101 \ TAxCCR0
15352 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15353 \ ------------------------------\
15354 \ %0000 0000 0001 0000 \ TAxCCTL0
15355 \ - \ CAP capture/compare mode = compare
15358 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
15359 \ ------------------------------\
15360 \ define LPM mode for ACCEPT \
15361 \ ------------------------------\
15362 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
15363 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15364 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15365 \ ------------------------------\
15367 \ ------------------------------\
15369 \ ------------------------------\
15370 #1000 20_US \ 1- wait 20 ms
15371 %011 TOP_LCD \ 2- send DB5=DB4=1
15372 #205 20_US \ 3- wait 4,1 ms
15373 %011 TOP_LCD \ 4- send again DB5=DB4=1
15374 #5 20_US \ 5- wait 0,1 ms
15375 %011 TOP_LCD \ 6- send again again DB5=DB4=1
15376 #2 20_US \ wait 40 us = LCD cycle
15377 %010 TOP_LCD \ 7- send DB5=1 DB4=0
15378 #2 20_US \ wait 40 us = LCD cycle
15379 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15380 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15381 LCD_CLEAR \ 10- "LCD_Clear"
15382 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15383 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15384 LCD_CLEAR \ 10- "LCD_Clear"
15385 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15386 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15387 CR ." I love you" \ display message on LCD
15388 ['] CR >BODY IS CR \ CR executes its default value
15389 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
15390 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15393 \ ------------------------------\
15395 \ ------------------------------\
15396 CODE START \ this routine replaces WARM and COLD default values by these of this application.
15397 \ ------------------------------\
15398 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
15399 0= IF \ if not done, customizes MARKER_DOES
15400 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
15401 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
15402 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
15403 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
15404 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15405 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
15406 MOV #RC5_INT,&IR_VEC \ init interrupt vector
15407 MOV #INI_R2L,PC \ then execute new INI_APP, without return
15411 \ ------------------------------\
15414 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
15416 MARKER {RC5TOLCD} \ restore the state before MARKER definition
15417 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
15418 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
15419 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
15420 \ {RC5TOLCD}+14: make room to save previous IR_VEC
15422 [UNDEFINED] CONSTANT [IF]
15423 \ https://forth-standard.org/standard/core/CONSTANT
15424 \ CONSTANT <name> n -- define a Forth CONSTANT
15428 MOV TOS,-2(W) \ PFA = n
15435 [UNDEFINED] STATE [IF]
15436 \ https://forth-standard.org/standard/core/STATE
15437 \ STATE -- a-addr holds compiler state
15438 STATEADR CONSTANT STATE
15442 \ https://forth-standard.org/standard/core/Equal
15443 \ = x1 x2 -- flag test x1=x2
15450 XOR #-1,TOS \ 1 flag Z = 1
15455 [UNDEFINED] IF [IF] \ define IF and THEN
15456 \ https://forth-standard.org/standard/core/IF
15457 \ IF -- IFadr initialize conditional forward branch
15458 CODE IF \ immediate
15461 MOV &DP,TOS \ -- HERE
15462 ADD #4,&DP \ compile one word, reserve one word
15463 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
15464 ADD #2,TOS \ -- HERE+2=IFadr
15468 \ https://forth-standard.org/standard/core/THEN
15469 \ THEN IFadr -- resolve forward branch
15470 CODE THEN \ immediate
15471 MOV &DP,0(TOS) \ -- IFadr
15477 [UNDEFINED] ELSE [IF]
15478 \ https://forth-standard.org/standard/core/ELSE
15479 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
15480 CODE ELSE \ immediate
15481 ADD #4,&DP \ make room to compile two words
15482 MOV &DP,W \ W=HERE+4
15484 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
15486 MOV W,TOS \ -- ELSEadr
15491 [UNDEFINED] IS [IF] \ define DEFER! and IS
15493 \ https://forth-standard.org/standard/core/DEFERStore
15494 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
15495 CODE DEFER! \ xt2 xt1 --
15496 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
15501 \ https://forth-standard.org/standard/core/IS
15504 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
15505 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
15506 \ or in a definition : ... ['] U. IS DISPLAY ...
15507 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
15509 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
15513 IF POSTPONE ['] POSTPONE DEFER!
15519 [UNDEFINED] >BODY [IF]
15520 \ https://forth-standard.org/standard/core/toBODY
15521 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
15528 \ CODE 20uS \ n -- 8MHz version
15529 \ BEGIN \ 4 + 16 ~ loop
15530 \ MOV #39,rDOCON \ 39
15537 \ MOV #XDOCON,rDOCON \ 2
15542 CODE 20_US \ n -- n * 20 us
15543 BEGIN \ here we presume that LCD_TIM_IFG = 1...
15545 BIT #1,&LCD_TIM_CTL \ 3
15546 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15547 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15549 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15554 CODE TOP_LCD \ LCD Sample
15555 \ \ if write : %xxxx_WWWW --
15556 \ \ if read : -- %0000_RRRR
15557 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15558 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15559 0= IF \ write LCD bits pattern
15560 AND.B #LCD_DB,TOS \
15561 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15562 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15565 THEN \ read LCD bits pattern
15568 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15569 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15570 AND.B #LCD_DB,TOS \
15574 CODE LCD_WRC \ char -- Write Char
15575 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15577 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
15578 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
15579 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15580 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15581 COLON \ high level word starts here
15582 TOP_LCD 2 20_US \ write high nibble first
15586 CODE LCD_WRF \ func -- Write Fonction
15587 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15591 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
15592 : LCD_HOME $02 LCD_WRF 100 20_us ;
15594 \ [UNDEFINED] OR [IF]
15596 \ \ https://forth-standard.org/standard/core/OR
15597 \ \ C OR x1 x2 -- x3 logical OR
15605 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
15606 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
15607 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
15608 \ : LCD_FN_SET $20 OR LCD_WrF ;
15609 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
15610 \ : LCD_GOTO $80 OR LCD_WrF ;
15613 \ CODE LCD_RDS \ -- status Read Status
15614 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15615 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15616 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15617 \ COLON \ starts a FORTH word
15618 \ TOP_LCD 2 20_us \ -- %0000_HHHH
15619 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
15620 \ HI2LO \ switch from FORTH to assembler
15621 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
15622 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
15623 \ MOV @RSP+,IP \ restore IP saved by COLON
15627 \ CODE LCD_RDC \ -- char Read Char
15628 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15633 \ ******************************\
15634 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15635 \ ******************************\
15636 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
15637 BIT.B #SW2,&SW2_IN \ test switch S2
15638 0= IF \ case of switch S2 pressed
15639 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15641 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
15644 BIT.B #SW1,&SW1_IN \ test switch S1 input
15645 0= IF \ case of Switch S1 pressed
15646 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15648 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15655 \ ******************************\
15656 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
15657 \ ******************************\
15658 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15659 \ ******************************\
15660 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15661 \ \ SMclock = 8|16|24 MHz
15662 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15663 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15664 \ \ SR(9)=new Toggle bit memory (ADD on)
15665 \ ******************************\
15666 \ RC5_FirstStartBitHalfCycle: \
15667 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15668 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
15669 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
15671 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
15672 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
15674 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
15675 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
15677 MOV #1778,X \ RC5_Period * 1us
15678 MOV #14,W \ count of loop
15680 \ ******************************\
15681 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
15682 \ ******************************\ |
15683 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15684 \ RC5_Compute_3/4_Period: \ |
15685 RRUM #1,X \ X=1/2 cycle |
15688 ADD X,Y \ Y=3/4 cycle
15689 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
15691 \ ******************************\
15692 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15693 \ ******************************\
15694 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15695 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
15696 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15697 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15698 SUB #1,W \ decrement count loop
15699 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
15700 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15701 0<> WHILE \ ----> out of loop ----+
15702 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15704 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
15705 CMP Y,X \ 1 | cycle time out of bound ?
15706 U>= IF \ 2 ^ | yes:
15707 BIC #$30,&RC5_TIM_CTL \ | | stop timer
15708 GOTO FW1 \ | | quit on truncated RC5 message
15710 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
15712 REPEAT \ ----> loop back --+ | with X = new RC5_period value
15713 \ ******************************\ |
15714 \ RC5_SampleEndOf: \ <---------------------+
15715 \ ******************************\
15716 BIC #$30,&RC5_TIM_CTL \ stop timer
15717 \ ******************************\
15718 \ RC5_ComputeNewRC5word \
15719 \ ******************************\
15720 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
15721 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
15722 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
15723 \ ******************************\
15724 \ RC5_ComputeC6bit \
15725 \ ******************************\
15726 BIT #BIT14,T \ test /C6 bit in T
15727 0= IF BIS #BIT6,X \ set C6 bit in X
15728 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
15729 \ ******************************\
15730 \ RC5_CommandByteIsDone \ -- BASE RC5_code
15731 \ ******************************\
15732 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
15733 \ ******************************\
15734 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
15735 XOR @RSP,T \ (new XOR old) Toggle bits
15736 BIT #UF10,T \ repeated RC5_command ?
15737 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
15738 XOR #UF10,0(RSP) \ 5 toggle bit memory
15739 \ ******************************\
15740 \ Display IR_RC5 code \
15741 \ ******************************\
15742 SUB #8,PSP \ TOS -- x x x x TOS
15743 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
15744 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
15745 MOV #$10,&BASEADR \ set hexadecimal base
15746 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
15747 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
15748 LO2HI \ switch from assembler to FORTH
15749 LCD_CLEAR \ set LCD cursor at home
15750 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
15751 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
15752 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
15753 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
15754 HI2LO \ -- switch from FORTH to assembler
15755 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
15756 MOV @PSP+,TOS \ -- TOS
15758 MOV @RSP+,SR \ restore SR flags
15759 BIC #%1111_1000,SR \ but force CPU Active Mode
15760 RET \ (instead of RETI)
15764 \ ------------------------------\
15765 HDNCODE STOP_R2L \ define new STOP_APP
15766 \ ------------------------------\
15767 CMP #RET_ADR,&{RC5TOLCD}+8 \
15768 0<> IF \ if previous START executing
15769 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
15770 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
15771 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
15772 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
15773 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
15774 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
15775 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
15776 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
15777 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
15778 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
15783 \ ------------------------------\
15785 \ ------------------------------\
15786 BW1 \ <-- INI_R2L for some events
15788 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15790 ." RC5toLCD is removed,"
15791 ." type START to restart"
15794 \ ------------------------------\
15796 \ ------------------------------\
15797 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
15798 \ ------------------------------\
15800 \ ------------------------------\
15801 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
15802 \ ------------------------------\
15803 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
15804 \ ------------------------------\
15805 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
15806 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
15808 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
15809 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
15811 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
15812 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
15813 \ CMP #4,TOS \ hardware RST
15814 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
15815 \ CMP #2,TOS \ Power_ON event
15816 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
15818 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
15820 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
15822 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
15823 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
15824 \ ------------------------------\
15825 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15826 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15827 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15828 \ -- \ID input divider \ 10 = /4
15829 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15830 \ - \TBCLR TimerB Clear
15833 \ -------------------------------\
15834 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15835 \ -- \CM Capture Mode
15840 \ --- \OUTMOD \ 011 = set/reset
15846 \ -------------------------------\
15848 \ -------------------------------\
15850 \ ------------------------------\
15851 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15852 \ ------------------------------\
15853 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15854 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15855 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
15856 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15858 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
15859 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15861 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
15862 \ ------------------------------\
15863 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15864 \ ------------------------------\
15865 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
15866 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15867 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15868 \ ------------------------------\
15869 BIS.B #LCDVo,&LCDVo_DIR \
15870 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
15871 \ ------------------------------\
15872 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15873 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15874 \ ------------------------------\
15875 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15876 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15877 \ ******************************\
15879 \ ******************************\
15880 BIS.B #RC5,&IR_IE \ enable RC5_Int
15881 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15882 \ ******************************\
15883 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15884 \ ******************************\
15885 \ %01 0001 0100 \ TAxCTL
15886 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
15887 \ -- \ ID divided by 1
15888 \ -- \ MC MODE = up to TAxCCRn
15889 \ - \ TACLR clear timer count
15892 \ ------------------------------\
15893 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
15894 \ ------------------------------\
15896 \ --- \ TAIDEX pre divisor
15897 \ ------------------------------\
15898 \ %0000 0000 0000 0101 \ TAxCCR0
15899 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15900 \ ------------------------------\
15901 \ %0000 0000 0001 0000 \ TAxCCTL0
15902 \ - \ CAP capture/compare mode = compare
15905 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
15906 \ ------------------------------\
15907 \ define LPM mode for ACCEPT \
15908 \ ------------------------------\
15909 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
15910 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15911 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15912 \ ------------------------------\
15914 \ ------------------------------\
15916 \ ------------------------------\
15917 #1000 20_US \ 1- wait 20 ms
15918 %011 TOP_LCD \ 2- send DB5=DB4=1
15919 #205 20_US \ 3- wait 4,1 ms
15920 %011 TOP_LCD \ 4- send again DB5=DB4=1
15921 #5 20_US \ 5- wait 0,1 ms
15922 %011 TOP_LCD \ 6- send again again DB5=DB4=1
15923 #2 20_US \ wait 40 us = LCD cycle
15924 %010 TOP_LCD \ 7- send DB5=1 DB4=0
15925 #2 20_US \ wait 40 us = LCD cycle
15926 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15927 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15928 LCD_CLEAR \ 10- "LCD_Clear"
15929 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15930 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15931 LCD_CLEAR \ 10- "LCD_Clear"
15932 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15933 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15934 CR ." I love you" \ display message on LCD
15935 ['] CR >BODY IS CR \ CR executes its default value
15936 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
15937 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15940 \ ------------------------------\
15942 \ ------------------------------\
15943 CODE START \ this routine replaces WARM and COLD default values by these of this application.
15944 \ ------------------------------\
15945 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
15946 0= IF \ if not done, customizes MARKER_DOES
15947 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
15948 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
15949 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
15950 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
15951 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15952 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
15953 MOV #RC5_INT,&IR_VEC \ init interrupt vector
15954 MOV #INI_R2L,PC \ then execute new INI_APP, without return
15958 \ ------------------------------\
15961 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
15963 MARKER {RC5TOLCD} \ restore the state before MARKER definition
15964 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
15965 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
15966 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
15967 \ {RC5TOLCD}+14: make room to save previous IR_VEC
15969 [UNDEFINED] CONSTANT [IF]
15970 \ https://forth-standard.org/standard/core/CONSTANT
15971 \ CONSTANT <name> n -- define a Forth CONSTANT
15975 MOV TOS,-2(W) \ PFA = n
15982 [UNDEFINED] STATE [IF]
15983 \ https://forth-standard.org/standard/core/STATE
15984 \ STATE -- a-addr holds compiler state
15985 STATEADR CONSTANT STATE
15989 \ https://forth-standard.org/standard/core/Equal
15990 \ = x1 x2 -- flag test x1=x2
15997 XOR #-1,TOS \ 1 flag Z = 1
16002 [UNDEFINED] IF [IF] \ define IF and THEN
16003 \ https://forth-standard.org/standard/core/IF
16004 \ IF -- IFadr initialize conditional forward branch
16005 CODE IF \ immediate
16008 MOV &DP,TOS \ -- HERE
16009 ADD #4,&DP \ compile one word, reserve one word
16010 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
16011 ADD #2,TOS \ -- HERE+2=IFadr
16015 \ https://forth-standard.org/standard/core/THEN
16016 \ THEN IFadr -- resolve forward branch
16017 CODE THEN \ immediate
16018 MOV &DP,0(TOS) \ -- IFadr
16024 [UNDEFINED] ELSE [IF]
16025 \ https://forth-standard.org/standard/core/ELSE
16026 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
16027 CODE ELSE \ immediate
16028 ADD #4,&DP \ make room to compile two words
16029 MOV &DP,W \ W=HERE+4
16031 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
16033 MOV W,TOS \ -- ELSEadr
16038 [UNDEFINED] IS [IF] \ define DEFER! and IS
16040 \ https://forth-standard.org/standard/core/DEFERStore
16041 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
16042 CODE DEFER! \ xt2 xt1 --
16043 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
16048 \ https://forth-standard.org/standard/core/IS
16051 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
16052 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
16053 \ or in a definition : ... ['] U. IS DISPLAY ...
16054 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
16056 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
16060 IF POSTPONE ['] POSTPONE DEFER!
16066 [UNDEFINED] >BODY [IF]
16067 \ https://forth-standard.org/standard/core/toBODY
16068 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
16075 \ CODE 20uS \ n -- 8MHz version
16076 \ BEGIN \ 4 + 16 ~ loop
16077 \ MOV #39,rDOCON \ 39
16084 \ MOV #XDOCON,rDOCON \ 2
16089 CODE 20_US \ n -- n * 20 us
16090 BEGIN \ here we presume that LCD_TIM_IFG = 1...
16092 BIT #1,&LCD_TIM_CTL \ 3
16093 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
16094 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
16096 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
16101 CODE TOP_LCD \ LCD Sample
16102 \ \ if write : %xxxx_WWWW --
16103 \ \ if read : -- %0000_RRRR
16104 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16105 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16106 0= IF \ write LCD bits pattern
16107 AND.B #LCD_DB,TOS \
16108 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16109 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16112 THEN \ read LCD bits pattern
16115 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16116 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16117 AND.B #LCD_DB,TOS \
16121 CODE LCD_WRC \ char -- Write Char
16122 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16124 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
16125 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
16126 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16127 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16128 COLON \ high level word starts here
16129 TOP_LCD 2 20_US \ write high nibble first
16133 CODE LCD_WRF \ func -- Write Fonction
16134 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16138 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16139 : LCD_HOME $02 LCD_WRF 100 20_us ;
16141 \ [UNDEFINED] OR [IF]
16143 \ \ https://forth-standard.org/standard/core/OR
16144 \ \ C OR x1 x2 -- x3 logical OR
16152 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
16153 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
16154 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
16155 \ : LCD_FN_SET $20 OR LCD_WrF ;
16156 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
16157 \ : LCD_GOTO $80 OR LCD_WrF ;
16160 \ CODE LCD_RDS \ -- status Read Status
16161 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16162 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16163 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16164 \ COLON \ starts a FORTH word
16165 \ TOP_LCD 2 20_us \ -- %0000_HHHH
16166 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
16167 \ HI2LO \ switch from FORTH to assembler
16168 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
16169 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
16170 \ MOV @RSP+,IP \ restore IP saved by COLON
16174 \ CODE LCD_RDC \ -- char Read Char
16175 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16180 \ ******************************\
16181 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16182 \ ******************************\
16183 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
16184 BIT.B #SW2,&SW2_IN \ test switch S2
16185 0= IF \ case of switch S2 pressed
16186 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16188 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
16191 BIT.B #SW1,&SW1_IN \ test switch S1 input
16192 0= IF \ case of Switch S1 pressed
16193 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16195 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16202 \ ******************************\
16203 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
16204 \ ******************************\
16205 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16206 \ ******************************\
16207 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16208 \ \ SMclock = 8|16|24 MHz
16209 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16210 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16211 \ \ SR(9)=new Toggle bit memory (ADD on)
16212 \ ******************************\
16213 \ RC5_FirstStartBitHalfCycle: \
16214 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16215 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
16216 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
16218 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
16219 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
16221 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
16222 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
16224 MOV #1778,X \ RC5_Period * 1us
16225 MOV #14,W \ count of loop
16227 \ ******************************\
16228 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
16229 \ ******************************\ |
16230 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16231 \ RC5_Compute_3/4_Period: \ |
16232 RRUM #1,X \ X=1/2 cycle |
16235 ADD X,Y \ Y=3/4 cycle
16236 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
16238 \ ******************************\
16239 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16240 \ ******************************\
16241 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16242 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
16243 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16244 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16245 SUB #1,W \ decrement count loop
16246 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
16247 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16248 0<> WHILE \ ----> out of loop ----+
16249 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16251 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
16252 CMP Y,X \ 1 | cycle time out of bound ?
16253 U>= IF \ 2 ^ | yes:
16254 BIC #$30,&RC5_TIM_CTL \ | | stop timer
16255 GOTO FW1 \ | | quit on truncated RC5 message
16257 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
16259 REPEAT \ ----> loop back --+ | with X = new RC5_period value
16260 \ ******************************\ |
16261 \ RC5_SampleEndOf: \ <---------------------+
16262 \ ******************************\
16263 BIC #$30,&RC5_TIM_CTL \ stop timer
16264 \ ******************************\
16265 \ RC5_ComputeNewRC5word \
16266 \ ******************************\
16267 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
16268 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
16269 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
16270 \ ******************************\
16271 \ RC5_ComputeC6bit \
16272 \ ******************************\
16273 BIT #BIT14,T \ test /C6 bit in T
16274 0= IF BIS #BIT6,X \ set C6 bit in X
16275 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
16276 \ ******************************\
16277 \ RC5_CommandByteIsDone \ -- BASE RC5_code
16278 \ ******************************\
16279 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
16280 \ ******************************\
16281 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
16282 XOR @RSP,T \ (new XOR old) Toggle bits
16283 BIT #UF10,T \ repeated RC5_command ?
16284 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
16285 XOR #UF10,0(RSP) \ 5 toggle bit memory
16286 \ ******************************\
16287 \ Display IR_RC5 code \
16288 \ ******************************\
16289 SUB #8,PSP \ TOS -- x x x x TOS
16290 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
16291 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
16292 MOV #$10,&BASEADR \ set hexadecimal base
16293 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
16294 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
16295 LO2HI \ switch from assembler to FORTH
16296 LCD_CLEAR \ set LCD cursor at home
16297 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
16298 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
16299 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
16300 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
16301 HI2LO \ -- switch from FORTH to assembler
16302 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
16303 MOV @PSP+,TOS \ -- TOS
16305 MOV @RSP+,SR \ restore SR flags
16306 BIC #%1111_1000,SR \ but force CPU Active Mode
16307 RET \ (instead of RETI)
16311 \ ------------------------------\
16312 HDNCODE STOP_R2L \ define new STOP_APP
16313 \ ------------------------------\
16314 CMP #RET_ADR,&{RC5TOLCD}+8 \
16315 0<> IF \ if previous START executing
16316 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
16317 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
16318 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
16319 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
16320 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
16321 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
16322 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
16323 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
16324 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
16325 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
16330 \ ------------------------------\
16332 \ ------------------------------\
16333 BW1 \ <-- INI_R2L for some events
16335 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
16337 ." RC5toLCD is removed,"
16338 ." type START to restart"
16341 \ ------------------------------\
16343 \ ------------------------------\
16344 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
16345 \ ------------------------------\
16347 \ ------------------------------\
16348 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
16349 \ ------------------------------\
16350 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
16351 \ ------------------------------\
16352 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
16353 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
16355 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
16356 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
16358 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
16359 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
16360 \ CMP #4,TOS \ hardware RST
16361 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
16362 \ CMP #2,TOS \ Power_ON event
16363 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
16365 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
16367 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
16369 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
16370 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
16371 \ ------------------------------\
16372 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
16373 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16374 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16375 \ -- \ID input divider \ 10 = /4
16376 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
16377 \ - \TBCLR TimerB Clear
16380 \ -------------------------------\
16381 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16382 \ -- \CM Capture Mode
16387 \ --- \OUTMOD \ 011 = set/reset
16393 \ -------------------------------\
16395 \ -------------------------------\
16397 \ ------------------------------\
16398 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16399 \ ------------------------------\
16400 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16401 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16402 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
16403 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16405 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
16406 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16408 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
16409 \ ------------------------------\
16410 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16411 \ ------------------------------\
16412 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
16413 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16414 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16415 \ ------------------------------\
16416 BIS.B #LCDVo,&LCDVo_DIR \
16417 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
16418 \ ------------------------------\
16419 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16420 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16421 \ ------------------------------\
16422 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16423 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16424 \ ******************************\
16426 \ ******************************\
16427 BIS.B #RC5,&IR_IE \ enable RC5_Int
16428 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16429 \ ******************************\
16430 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16431 \ ******************************\
16432 \ %01 0001 0100 \ TAxCTL
16433 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
16434 \ -- \ ID divided by 1
16435 \ -- \ MC MODE = up to TAxCCRn
16436 \ - \ TACLR clear timer count
16439 \ ------------------------------\
16440 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
16441 \ ------------------------------\
16443 \ --- \ TAIDEX pre divisor
16444 \ ------------------------------\
16445 \ %0000 0000 0000 0101 \ TAxCCR0
16446 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16447 \ ------------------------------\
16448 \ %0000 0000 0001 0000 \ TAxCCTL0
16449 \ - \ CAP capture/compare mode = compare
16452 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
16453 \ ------------------------------\
16454 \ define LPM mode for ACCEPT \
16455 \ ------------------------------\
16456 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
16457 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16458 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16459 \ ------------------------------\
16461 \ ------------------------------\
16463 \ ------------------------------\
16464 #1000 20_US \ 1- wait 20 ms
16465 %011 TOP_LCD \ 2- send DB5=DB4=1
16466 #205 20_US \ 3- wait 4,1 ms
16467 %011 TOP_LCD \ 4- send again DB5=DB4=1
16468 #5 20_US \ 5- wait 0,1 ms
16469 %011 TOP_LCD \ 6- send again again DB5=DB4=1
16470 #2 20_US \ wait 40 us = LCD cycle
16471 %010 TOP_LCD \ 7- send DB5=1 DB4=0
16472 #2 20_US \ wait 40 us = LCD cycle
16473 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16474 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16475 LCD_CLEAR \ 10- "LCD_Clear"
16476 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16477 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16478 LCD_CLEAR \ 10- "LCD_Clear"
16479 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16480 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16481 CR ." I love you" \ display message on LCD
16482 ['] CR >BODY IS CR \ CR executes its default value
16483 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
16484 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16487 \ ------------------------------\
16489 \ ------------------------------\
16490 CODE START \ this routine replaces WARM and COLD default values by these of this application.
16491 \ ------------------------------\
16492 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
16493 0= IF \ if not done, customizes MARKER_DOES
16494 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
16495 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
16496 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
16497 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
16498 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16499 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
16500 MOV #RC5_INT,&IR_VEC \ init interrupt vector
16501 MOV #INI_R2L,PC \ then execute new INI_APP, without return
16505 \ ------------------------------\
16508 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
16510 MARKER {RC5TOLCD} \ restore the state before MARKER definition
16511 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
16512 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
16513 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
16514 \ {RC5TOLCD}+14: make room to save previous IR_VEC
16516 [UNDEFINED] CONSTANT [IF]
16517 \ https://forth-standard.org/standard/core/CONSTANT
16518 \ CONSTANT <name> n -- define a Forth CONSTANT
16522 MOV TOS,-2(W) \ PFA = n
16529 [UNDEFINED] STATE [IF]
16530 \ https://forth-standard.org/standard/core/STATE
16531 \ STATE -- a-addr holds compiler state
16532 STATEADR CONSTANT STATE
16536 \ https://forth-standard.org/standard/core/Equal
16537 \ = x1 x2 -- flag test x1=x2
16544 XOR #-1,TOS \ 1 flag Z = 1
16549 [UNDEFINED] IF [IF] \ define IF and THEN
16550 \ https://forth-standard.org/standard/core/IF
16551 \ IF -- IFadr initialize conditional forward branch
16552 CODE IF \ immediate
16555 MOV &DP,TOS \ -- HERE
16556 ADD #4,&DP \ compile one word, reserve one word
16557 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
16558 ADD #2,TOS \ -- HERE+2=IFadr
16562 \ https://forth-standard.org/standard/core/THEN
16563 \ THEN IFadr -- resolve forward branch
16564 CODE THEN \ immediate
16565 MOV &DP,0(TOS) \ -- IFadr
16571 [UNDEFINED] ELSE [IF]
16572 \ https://forth-standard.org/standard/core/ELSE
16573 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
16574 CODE ELSE \ immediate
16575 ADD #4,&DP \ make room to compile two words
16576 MOV &DP,W \ W=HERE+4
16578 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
16580 MOV W,TOS \ -- ELSEadr
16585 [UNDEFINED] IS [IF] \ define DEFER! and IS
16587 \ https://forth-standard.org/standard/core/DEFERStore
16588 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
16589 CODE DEFER! \ xt2 xt1 --
16590 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
16595 \ https://forth-standard.org/standard/core/IS
16598 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
16599 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
16600 \ or in a definition : ... ['] U. IS DISPLAY ...
16601 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
16603 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
16607 IF POSTPONE ['] POSTPONE DEFER!
16613 [UNDEFINED] >BODY [IF]
16614 \ https://forth-standard.org/standard/core/toBODY
16615 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
16622 \ CODE 20uS \ n -- 8MHz version
16623 \ BEGIN \ 4 + 16 ~ loop
16624 \ MOV #39,rDOCON \ 39
16631 \ MOV #XDOCON,rDOCON \ 2
16636 CODE 20_US \ n -- n * 20 us
16637 BEGIN \ here we presume that LCD_TIM_IFG = 1...
16639 BIT #1,&LCD_TIM_CTL \ 3
16640 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
16641 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
16643 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
16648 CODE TOP_LCD \ LCD Sample
16649 \ \ if write : %xxxx_WWWW --
16650 \ \ if read : -- %0000_RRRR
16651 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16652 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16653 0= IF \ write LCD bits pattern
16654 AND.B #LCD_DB,TOS \
16655 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16656 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16659 THEN \ read LCD bits pattern
16662 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16663 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16664 AND.B #LCD_DB,TOS \
16668 CODE LCD_WRC \ char -- Write Char
16669 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16671 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
16672 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
16673 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16674 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16675 COLON \ high level word starts here
16676 TOP_LCD 2 20_US \ write high nibble first
16680 CODE LCD_WRF \ func -- Write Fonction
16681 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16685 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16686 : LCD_HOME $02 LCD_WRF 100 20_us ;
16688 \ [UNDEFINED] OR [IF]
16690 \ \ https://forth-standard.org/standard/core/OR
16691 \ \ C OR x1 x2 -- x3 logical OR
16699 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
16700 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
16701 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
16702 \ : LCD_FN_SET $20 OR LCD_WrF ;
16703 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
16704 \ : LCD_GOTO $80 OR LCD_WrF ;
16707 \ CODE LCD_RDS \ -- status Read Status
16708 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16709 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16710 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16711 \ COLON \ starts a FORTH word
16712 \ TOP_LCD 2 20_us \ -- %0000_HHHH
16713 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
16714 \ HI2LO \ switch from FORTH to assembler
16715 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
16716 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
16717 \ MOV @RSP+,IP \ restore IP saved by COLON
16721 \ CODE LCD_RDC \ -- char Read Char
16722 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16727 \ ******************************\
16728 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16729 \ ******************************\
16730 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
16731 BIT.B #SW2,&SW2_IN \ test switch S2
16732 0= IF \ case of switch S2 pressed
16733 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16735 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
16738 BIT.B #SW1,&SW1_IN \ test switch S1 input
16739 0= IF \ case of Switch S1 pressed
16740 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16742 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16749 \ ******************************\
16750 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
16751 \ ******************************\
16752 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16753 \ ******************************\
16754 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16755 \ \ SMclock = 8|16|24 MHz
16756 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16757 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16758 \ \ SR(9)=new Toggle bit memory (ADD on)
16759 \ ******************************\
16760 \ RC5_FirstStartBitHalfCycle: \
16761 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16762 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
16763 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
16765 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
16766 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
16768 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
16769 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
16771 MOV #1778,X \ RC5_Period * 1us
16772 MOV #14,W \ count of loop
16774 \ ******************************\
16775 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
16776 \ ******************************\ |
16777 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16778 \ RC5_Compute_3/4_Period: \ |
16779 RRUM #1,X \ X=1/2 cycle |
16782 ADD X,Y \ Y=3/4 cycle
16783 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
16785 \ ******************************\
16786 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16787 \ ******************************\
16788 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16789 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
16790 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16791 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16792 SUB #1,W \ decrement count loop
16793 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
16794 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16795 0<> WHILE \ ----> out of loop ----+
16796 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16798 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
16799 CMP Y,X \ 1 | cycle time out of bound ?
16800 U>= IF \ 2 ^ | yes:
16801 BIC #$30,&RC5_TIM_CTL \ | | stop timer
16802 GOTO FW1 \ | | quit on truncated RC5 message
16804 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
16806 REPEAT \ ----> loop back --+ | with X = new RC5_period value
16807 \ ******************************\ |
16808 \ RC5_SampleEndOf: \ <---------------------+
16809 \ ******************************\
16810 BIC #$30,&RC5_TIM_CTL \ stop timer
16811 \ ******************************\
16812 \ RC5_ComputeNewRC5word \
16813 \ ******************************\
16814 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
16815 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
16816 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
16817 \ ******************************\
16818 \ RC5_ComputeC6bit \
16819 \ ******************************\
16820 BIT #BIT14,T \ test /C6 bit in T
16821 0= IF BIS #BIT6,X \ set C6 bit in X
16822 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
16823 \ ******************************\
16824 \ RC5_CommandByteIsDone \ -- BASE RC5_code
16825 \ ******************************\
16826 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
16827 \ ******************************\
16828 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
16829 XOR @RSP,T \ (new XOR old) Toggle bits
16830 BIT #UF10,T \ repeated RC5_command ?
16831 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
16832 XOR #UF10,0(RSP) \ 5 toggle bit memory
16833 \ ******************************\
16834 \ Display IR_RC5 code \
16835 \ ******************************\
16836 SUB #8,PSP \ TOS -- x x x x TOS
16837 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
16838 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
16839 MOV #$10,&BASEADR \ set hexadecimal base
16840 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
16841 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
16842 LO2HI \ switch from assembler to FORTH
16843 LCD_CLEAR \ set LCD cursor at home
16844 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
16845 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
16846 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
16847 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
16848 HI2LO \ -- switch from FORTH to assembler
16849 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
16850 MOV @PSP+,TOS \ -- TOS
16852 MOV @RSP+,SR \ restore SR flags
16853 BIC #%1111_1000,SR \ but force CPU Active Mode
16854 RET \ (instead of RETI)
16858 \ ------------------------------\
16859 HDNCODE STOP_R2L \ define new STOP_APP
16860 \ ------------------------------\
16861 CMP #RET_ADR,&{RC5TOLCD}+8 \
16862 0<> IF \ if previous START executing
16863 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
16864 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
16865 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
16866 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
16867 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
16868 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
16869 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
16870 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
16871 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
16872 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
16877 \ ------------------------------\
16879 \ ------------------------------\
16880 BW1 \ <-- INI_R2L for some events
16882 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
16884 ." RC5toLCD is removed,"
16885 ." type START to restart"
16888 \ ------------------------------\
16890 \ ------------------------------\
16891 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
16892 \ ------------------------------\
16894 \ ------------------------------\
16895 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
16896 \ ------------------------------\
16897 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
16898 \ ------------------------------\
16899 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
16900 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
16902 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
16903 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
16905 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
16906 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
16907 \ CMP #4,TOS \ hardware RST
16908 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
16909 \ CMP #2,TOS \ Power_ON event
16910 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
16912 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
16914 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
16916 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
16917 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
16918 \ ------------------------------\
16919 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
16920 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16921 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16922 \ -- \ID input divider \ 10 = /4
16923 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
16924 \ - \TBCLR TimerB Clear
16927 \ -------------------------------\
16928 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16929 \ -- \CM Capture Mode
16934 \ --- \OUTMOD \ 011 = set/reset
16940 \ -------------------------------\
16942 \ -------------------------------\
16944 \ ------------------------------\
16945 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16946 \ ------------------------------\
16947 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16948 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16949 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
16950 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16952 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
16953 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16955 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
16956 \ ------------------------------\
16957 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16958 \ ------------------------------\
16959 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
16960 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16961 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16962 \ ------------------------------\
16963 BIS.B #LCDVo,&LCDVo_DIR \
16964 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
16965 \ ------------------------------\
16966 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16967 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16968 \ ------------------------------\
16969 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16970 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16971 \ ******************************\
16973 \ ******************************\
16974 BIS.B #RC5,&IR_IE \ enable RC5_Int
16975 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16976 \ ******************************\
16977 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16978 \ ******************************\
16979 \ %01 0001 0100 \ TAxCTL
16980 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
16981 \ -- \ ID divided by 1
16982 \ -- \ MC MODE = up to TAxCCRn
16983 \ - \ TACLR clear timer count
16986 \ ------------------------------\
16987 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
16988 \ ------------------------------\
16990 \ --- \ TAIDEX pre divisor
16991 \ ------------------------------\
16992 \ %0000 0000 0000 0101 \ TAxCCR0
16993 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16994 \ ------------------------------\
16995 \ %0000 0000 0001 0000 \ TAxCCTL0
16996 \ - \ CAP capture/compare mode = compare
16999 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17000 \ ------------------------------\
17001 \ define LPM mode for ACCEPT \
17002 \ ------------------------------\
17003 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
17004 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17005 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17006 \ ------------------------------\
17008 \ ------------------------------\
17010 \ ------------------------------\
17011 #1000 20_US \ 1- wait 20 ms
17012 %011 TOP_LCD \ 2- send DB5=DB4=1
17013 #205 20_US \ 3- wait 4,1 ms
17014 %011 TOP_LCD \ 4- send again DB5=DB4=1
17015 #5 20_US \ 5- wait 0,1 ms
17016 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17017 #2 20_US \ wait 40 us = LCD cycle
17018 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17019 #2 20_US \ wait 40 us = LCD cycle
17020 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17021 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17022 LCD_CLEAR \ 10- "LCD_Clear"
17023 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17024 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17025 LCD_CLEAR \ 10- "LCD_Clear"
17026 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17027 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17028 CR ." I love you" \ display message on LCD
17029 ['] CR >BODY IS CR \ CR executes its default value
17030 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17031 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17034 \ ------------------------------\
17036 \ ------------------------------\
17037 CODE START \ this routine replaces WARM and COLD default values by these of this application.
17038 \ ------------------------------\
17039 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
17040 0= IF \ if not done, customizes MARKER_DOES
17041 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
17042 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
17043 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
17044 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
17045 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17046 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
17047 MOV #RC5_INT,&IR_VEC \ init interrupt vector
17048 MOV #INI_R2L,PC \ then execute new INI_APP, without return
17052 \ ------------------------------\
17055 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
17057 MARKER {RC5TOLCD} \ restore the state before MARKER definition
17058 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
17059 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
17060 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
17061 \ {RC5TOLCD}+14: make room to save previous IR_VEC
17063 [UNDEFINED] CONSTANT [IF]
17064 \ https://forth-standard.org/standard/core/CONSTANT
17065 \ CONSTANT <name> n -- define a Forth CONSTANT
17069 MOV TOS,-2(W) \ PFA = n
17076 [UNDEFINED] STATE [IF]
17077 \ https://forth-standard.org/standard/core/STATE
17078 \ STATE -- a-addr holds compiler state
17079 STATEADR CONSTANT STATE
17083 \ https://forth-standard.org/standard/core/Equal
17084 \ = x1 x2 -- flag test x1=x2
17091 XOR #-1,TOS \ 1 flag Z = 1
17096 [UNDEFINED] IF [IF] \ define IF and THEN
17097 \ https://forth-standard.org/standard/core/IF
17098 \ IF -- IFadr initialize conditional forward branch
17099 CODE IF \ immediate
17102 MOV &DP,TOS \ -- HERE
17103 ADD #4,&DP \ compile one word, reserve one word
17104 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
17105 ADD #2,TOS \ -- HERE+2=IFadr
17109 \ https://forth-standard.org/standard/core/THEN
17110 \ THEN IFadr -- resolve forward branch
17111 CODE THEN \ immediate
17112 MOV &DP,0(TOS) \ -- IFadr
17118 [UNDEFINED] ELSE [IF]
17119 \ https://forth-standard.org/standard/core/ELSE
17120 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
17121 CODE ELSE \ immediate
17122 ADD #4,&DP \ make room to compile two words
17123 MOV &DP,W \ W=HERE+4
17125 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
17127 MOV W,TOS \ -- ELSEadr
17132 [UNDEFINED] IS [IF] \ define DEFER! and IS
17134 \ https://forth-standard.org/standard/core/DEFERStore
17135 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
17136 CODE DEFER! \ xt2 xt1 --
17137 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
17142 \ https://forth-standard.org/standard/core/IS
17145 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
17146 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
17147 \ or in a definition : ... ['] U. IS DISPLAY ...
17148 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
17150 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
17154 IF POSTPONE ['] POSTPONE DEFER!
17160 [UNDEFINED] >BODY [IF]
17161 \ https://forth-standard.org/standard/core/toBODY
17162 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
17169 \ CODE 20uS \ n -- 8MHz version
17170 \ BEGIN \ 4 + 16 ~ loop
17171 \ MOV #39,rDOCON \ 39
17178 \ MOV #XDOCON,rDOCON \ 2
17183 CODE 20_US \ n -- n * 20 us
17184 BEGIN \ here we presume that LCD_TIM_IFG = 1...
17186 BIT #1,&LCD_TIM_CTL \ 3
17187 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
17188 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
17190 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
17195 CODE TOP_LCD \ LCD Sample
17196 \ \ if write : %xxxx_WWWW --
17197 \ \ if read : -- %0000_RRRR
17198 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17199 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17200 0= IF \ write LCD bits pattern
17201 AND.B #LCD_DB,TOS \
17202 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17203 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17206 THEN \ read LCD bits pattern
17209 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17210 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17211 AND.B #LCD_DB,TOS \
17215 CODE LCD_WRC \ char -- Write Char
17216 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17218 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
17219 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
17220 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17221 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17222 COLON \ high level word starts here
17223 TOP_LCD 2 20_US \ write high nibble first
17227 CODE LCD_WRF \ func -- Write Fonction
17228 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17232 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
17233 : LCD_HOME $02 LCD_WRF 100 20_us ;
17235 \ [UNDEFINED] OR [IF]
17237 \ \ https://forth-standard.org/standard/core/OR
17238 \ \ C OR x1 x2 -- x3 logical OR
17246 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
17247 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
17248 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
17249 \ : LCD_FN_SET $20 OR LCD_WrF ;
17250 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
17251 \ : LCD_GOTO $80 OR LCD_WrF ;
17254 \ CODE LCD_RDS \ -- status Read Status
17255 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17256 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17257 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17258 \ COLON \ starts a FORTH word
17259 \ TOP_LCD 2 20_us \ -- %0000_HHHH
17260 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
17261 \ HI2LO \ switch from FORTH to assembler
17262 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
17263 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
17264 \ MOV @RSP+,IP \ restore IP saved by COLON
17268 \ CODE LCD_RDC \ -- char Read Char
17269 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17274 \ ******************************\
17275 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17276 \ ******************************\
17277 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
17278 BIT.B #SW2,&SW2_IN \ test switch S2
17279 0= IF \ case of switch S2 pressed
17280 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17282 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
17285 BIT.B #SW1,&SW1_IN \ test switch S1 input
17286 0= IF \ case of Switch S1 pressed
17287 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17289 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17296 \ ******************************\
17297 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
17298 \ ******************************\
17299 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17300 \ ******************************\
17301 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17302 \ \ SMclock = 8|16|24 MHz
17303 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17304 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17305 \ \ SR(9)=new Toggle bit memory (ADD on)
17306 \ ******************************\
17307 \ RC5_FirstStartBitHalfCycle: \
17308 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17309 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
17310 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
17312 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
17313 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
17315 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
17316 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
17318 MOV #1778,X \ RC5_Period * 1us
17319 MOV #14,W \ count of loop
17321 \ ******************************\
17322 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
17323 \ ******************************\ |
17324 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17325 \ RC5_Compute_3/4_Period: \ |
17326 RRUM #1,X \ X=1/2 cycle |
17329 ADD X,Y \ Y=3/4 cycle
17330 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
17332 \ ******************************\
17333 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17334 \ ******************************\
17335 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17336 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
17337 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17338 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17339 SUB #1,W \ decrement count loop
17340 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
17341 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17342 0<> WHILE \ ----> out of loop ----+
17343 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17345 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
17346 CMP Y,X \ 1 | cycle time out of bound ?
17347 U>= IF \ 2 ^ | yes:
17348 BIC #$30,&RC5_TIM_CTL \ | | stop timer
17349 GOTO FW1 \ | | quit on truncated RC5 message
17351 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
17353 REPEAT \ ----> loop back --+ | with X = new RC5_period value
17354 \ ******************************\ |
17355 \ RC5_SampleEndOf: \ <---------------------+
17356 \ ******************************\
17357 BIC #$30,&RC5_TIM_CTL \ stop timer
17358 \ ******************************\
17359 \ RC5_ComputeNewRC5word \
17360 \ ******************************\
17361 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
17362 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
17363 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
17364 \ ******************************\
17365 \ RC5_ComputeC6bit \
17366 \ ******************************\
17367 BIT #BIT14,T \ test /C6 bit in T
17368 0= IF BIS #BIT6,X \ set C6 bit in X
17369 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
17370 \ ******************************\
17371 \ RC5_CommandByteIsDone \ -- BASE RC5_code
17372 \ ******************************\
17373 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
17374 \ ******************************\
17375 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
17376 XOR @RSP,T \ (new XOR old) Toggle bits
17377 BIT #UF10,T \ repeated RC5_command ?
17378 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
17379 XOR #UF10,0(RSP) \ 5 toggle bit memory
17380 \ ******************************\
17381 \ Display IR_RC5 code \
17382 \ ******************************\
17383 SUB #8,PSP \ TOS -- x x x x TOS
17384 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
17385 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
17386 MOV #$10,&BASEADR \ set hexadecimal base
17387 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
17388 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
17389 LO2HI \ switch from assembler to FORTH
17390 LCD_CLEAR \ set LCD cursor at home
17391 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17392 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17393 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17394 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17395 HI2LO \ -- switch from FORTH to assembler
17396 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17397 MOV @PSP+,TOS \ -- TOS
17399 MOV @RSP+,SR \ restore SR flags
17400 BIC #%1111_1000,SR \ but force CPU Active Mode
17401 RET \ (instead of RETI)
17405 \ ------------------------------\
17406 HDNCODE STOP_R2L \ define new STOP_APP
17407 \ ------------------------------\
17408 CMP #RET_ADR,&{RC5TOLCD}+8 \
17409 0<> IF \ if previous START executing
17410 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
17411 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
17412 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
17413 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
17414 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
17415 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
17416 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
17417 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
17418 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
17419 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
17424 \ ------------------------------\
17426 \ ------------------------------\
17427 BW1 \ <-- INI_R2L for some events
17429 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17431 ." RC5toLCD is removed,"
17432 ." type START to restart"
17435 \ ------------------------------\
17437 \ ------------------------------\
17438 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
17439 \ ------------------------------\
17441 \ ------------------------------\
17442 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
17443 \ ------------------------------\
17444 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
17445 \ ------------------------------\
17446 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
17447 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
17449 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
17450 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
17452 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
17453 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
17454 \ CMP #4,TOS \ hardware RST
17455 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
17456 \ CMP #2,TOS \ Power_ON event
17457 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
17459 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
17461 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
17463 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
17464 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
17465 \ ------------------------------\
17466 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
17467 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17468 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17469 \ -- \ID input divider \ 10 = /4
17470 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17471 \ - \TBCLR TimerB Clear
17474 \ -------------------------------\
17475 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17476 \ -- \CM Capture Mode
17481 \ --- \OUTMOD \ 011 = set/reset
17487 \ -------------------------------\
17489 \ -------------------------------\
17491 \ ------------------------------\
17492 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17493 \ ------------------------------\
17494 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17495 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17496 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
17497 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17499 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
17500 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17502 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
17503 \ ------------------------------\
17504 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17505 \ ------------------------------\
17506 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
17507 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17508 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17509 \ ------------------------------\
17510 BIS.B #LCDVo,&LCDVo_DIR \
17511 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
17512 \ ------------------------------\
17513 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17514 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17515 \ ------------------------------\
17516 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17517 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17518 \ ******************************\
17520 \ ******************************\
17521 BIS.B #RC5,&IR_IE \ enable RC5_Int
17522 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17523 \ ******************************\
17524 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17525 \ ******************************\
17526 \ %01 0001 0100 \ TAxCTL
17527 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
17528 \ -- \ ID divided by 1
17529 \ -- \ MC MODE = up to TAxCCRn
17530 \ - \ TACLR clear timer count
17533 \ ------------------------------\
17534 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
17535 \ ------------------------------\
17537 \ --- \ TAIDEX pre divisor
17538 \ ------------------------------\
17539 \ %0000 0000 0000 0101 \ TAxCCR0
17540 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17541 \ ------------------------------\
17542 \ %0000 0000 0001 0000 \ TAxCCTL0
17543 \ - \ CAP capture/compare mode = compare
17546 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17547 \ ------------------------------\
17548 \ define LPM mode for ACCEPT \
17549 \ ------------------------------\
17550 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
17551 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17552 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17553 \ ------------------------------\
17555 \ ------------------------------\
17557 \ ------------------------------\
17558 #1000 20_US \ 1- wait 20 ms
17559 %011 TOP_LCD \ 2- send DB5=DB4=1
17560 #205 20_US \ 3- wait 4,1 ms
17561 %011 TOP_LCD \ 4- send again DB5=DB4=1
17562 #5 20_US \ 5- wait 0,1 ms
17563 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17564 #2 20_US \ wait 40 us = LCD cycle
17565 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17566 #2 20_US \ wait 40 us = LCD cycle
17567 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17568 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17569 LCD_CLEAR \ 10- "LCD_Clear"
17570 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17571 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17572 LCD_CLEAR \ 10- "LCD_Clear"
17573 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17574 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17575 CR ." I love you" \ display message on LCD
17576 ['] CR >BODY IS CR \ CR executes its default value
17577 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17578 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17581 \ ------------------------------\
17583 \ ------------------------------\
17584 CODE START \ this routine replaces WARM and COLD default values by these of this application.
17585 \ ------------------------------\
17586 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
17587 0= IF \ if not done, customizes MARKER_DOES
17588 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
17589 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
17590 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
17591 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
17592 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17593 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
17594 MOV #RC5_INT,&IR_VEC \ init interrupt vector
17595 MOV #INI_R2L,PC \ then execute new INI_APP, without return
17599 \ ------------------------------\
17602 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
17604 MARKER {RC5TOLCD} \ restore the state before MARKER definition
17605 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
17606 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
17607 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
17608 \ {RC5TOLCD}+14: make room to save previous IR_VEC
17610 [UNDEFINED] CONSTANT [IF]
17611 \ https://forth-standard.org/standard/core/CONSTANT
17612 \ CONSTANT <name> n -- define a Forth CONSTANT
17616 MOV TOS,-2(W) \ PFA = n
17623 [UNDEFINED] STATE [IF]
17624 \ https://forth-standard.org/standard/core/STATE
17625 \ STATE -- a-addr holds compiler state
17626 STATEADR CONSTANT STATE
17630 \ https://forth-standard.org/standard/core/Equal
17631 \ = x1 x2 -- flag test x1=x2
17638 XOR #-1,TOS \ 1 flag Z = 1
17643 [UNDEFINED] IF [IF] \ define IF and THEN
17644 \ https://forth-standard.org/standard/core/IF
17645 \ IF -- IFadr initialize conditional forward branch
17646 CODE IF \ immediate
17649 MOV &DP,TOS \ -- HERE
17650 ADD #4,&DP \ compile one word, reserve one word
17651 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
17652 ADD #2,TOS \ -- HERE+2=IFadr
17656 \ https://forth-standard.org/standard/core/THEN
17657 \ THEN IFadr -- resolve forward branch
17658 CODE THEN \ immediate
17659 MOV &DP,0(TOS) \ -- IFadr
17665 [UNDEFINED] ELSE [IF]
17666 \ https://forth-standard.org/standard/core/ELSE
17667 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
17668 CODE ELSE \ immediate
17669 ADD #4,&DP \ make room to compile two words
17670 MOV &DP,W \ W=HERE+4
17672 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
17674 MOV W,TOS \ -- ELSEadr
17679 [UNDEFINED] IS [IF] \ define DEFER! and IS
17681 \ https://forth-standard.org/standard/core/DEFERStore
17682 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
17683 CODE DEFER! \ xt2 xt1 --
17684 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
17689 \ https://forth-standard.org/standard/core/IS
17692 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
17693 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
17694 \ or in a definition : ... ['] U. IS DISPLAY ...
17695 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
17697 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
17701 IF POSTPONE ['] POSTPONE DEFER!
17707 [UNDEFINED] >BODY [IF]
17708 \ https://forth-standard.org/standard/core/toBODY
17709 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
17716 \ CODE 20uS \ n -- 8MHz version
17717 \ BEGIN \ 4 + 16 ~ loop
17718 \ MOV #39,rDOCON \ 39
17725 \ MOV #XDOCON,rDOCON \ 2
17730 CODE 20_US \ n -- n * 20 us
17731 BEGIN \ here we presume that LCD_TIM_IFG = 1...
17733 BIT #1,&LCD_TIM_CTL \ 3
17734 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
17735 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
17737 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
17742 CODE TOP_LCD \ LCD Sample
17743 \ \ if write : %xxxx_WWWW --
17744 \ \ if read : -- %0000_RRRR
17745 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17746 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17747 0= IF \ write LCD bits pattern
17748 AND.B #LCD_DB,TOS \
17749 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17750 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17753 THEN \ read LCD bits pattern
17756 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17757 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17758 AND.B #LCD_DB,TOS \
17762 CODE LCD_WRC \ char -- Write Char
17763 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17765 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
17766 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
17767 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17768 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17769 COLON \ high level word starts here
17770 TOP_LCD 2 20_US \ write high nibble first
17774 CODE LCD_WRF \ func -- Write Fonction
17775 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17779 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
17780 : LCD_HOME $02 LCD_WRF 100 20_us ;
17782 \ [UNDEFINED] OR [IF]
17784 \ \ https://forth-standard.org/standard/core/OR
17785 \ \ C OR x1 x2 -- x3 logical OR
17793 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
17794 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
17795 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
17796 \ : LCD_FN_SET $20 OR LCD_WrF ;
17797 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
17798 \ : LCD_GOTO $80 OR LCD_WrF ;
17801 \ CODE LCD_RDS \ -- status Read Status
17802 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17803 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17804 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17805 \ COLON \ starts a FORTH word
17806 \ TOP_LCD 2 20_us \ -- %0000_HHHH
17807 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
17808 \ HI2LO \ switch from FORTH to assembler
17809 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
17810 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
17811 \ MOV @RSP+,IP \ restore IP saved by COLON
17815 \ CODE LCD_RDC \ -- char Read Char
17816 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17821 \ ******************************\
17822 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17823 \ ******************************\
17824 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
17825 BIT.B #SW2,&SW2_IN \ test switch S2
17826 0= IF \ case of switch S2 pressed
17827 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17829 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
17832 BIT.B #SW1,&SW1_IN \ test switch S1 input
17833 0= IF \ case of Switch S1 pressed
17834 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17836 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17843 \ ******************************\
17844 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
17845 \ ******************************\
17846 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17847 \ ******************************\
17848 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17849 \ \ SMclock = 8|16|24 MHz
17850 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17851 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17852 \ \ SR(9)=new Toggle bit memory (ADD on)
17853 \ ******************************\
17854 \ RC5_FirstStartBitHalfCycle: \
17855 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17856 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
17857 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
17859 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
17860 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
17862 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
17863 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
17865 MOV #1778,X \ RC5_Period * 1us
17866 MOV #14,W \ count of loop
17868 \ ******************************\
17869 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
17870 \ ******************************\ |
17871 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17872 \ RC5_Compute_3/4_Period: \ |
17873 RRUM #1,X \ X=1/2 cycle |
17876 ADD X,Y \ Y=3/4 cycle
17877 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
17879 \ ******************************\
17880 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17881 \ ******************************\
17882 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17883 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
17884 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17885 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17886 SUB #1,W \ decrement count loop
17887 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
17888 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17889 0<> WHILE \ ----> out of loop ----+
17890 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17892 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
17893 CMP Y,X \ 1 | cycle time out of bound ?
17894 U>= IF \ 2 ^ | yes:
17895 BIC #$30,&RC5_TIM_CTL \ | | stop timer
17896 GOTO FW1 \ | | quit on truncated RC5 message
17898 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
17900 REPEAT \ ----> loop back --+ | with X = new RC5_period value
17901 \ ******************************\ |
17902 \ RC5_SampleEndOf: \ <---------------------+
17903 \ ******************************\
17904 BIC #$30,&RC5_TIM_CTL \ stop timer
17905 \ ******************************\
17906 \ RC5_ComputeNewRC5word \
17907 \ ******************************\
17908 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
17909 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
17910 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
17911 \ ******************************\
17912 \ RC5_ComputeC6bit \
17913 \ ******************************\
17914 BIT #BIT14,T \ test /C6 bit in T
17915 0= IF BIS #BIT6,X \ set C6 bit in X
17916 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
17917 \ ******************************\
17918 \ RC5_CommandByteIsDone \ -- BASE RC5_code
17919 \ ******************************\
17920 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
17921 \ ******************************\
17922 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
17923 XOR @RSP,T \ (new XOR old) Toggle bits
17924 BIT #UF10,T \ repeated RC5_command ?
17925 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
17926 XOR #UF10,0(RSP) \ 5 toggle bit memory
17927 \ ******************************\
17928 \ Display IR_RC5 code \
17929 \ ******************************\
17930 SUB #8,PSP \ TOS -- x x x x TOS
17931 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
17932 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
17933 MOV #$10,&BASEADR \ set hexadecimal base
17934 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
17935 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
17936 LO2HI \ switch from assembler to FORTH
17937 LCD_CLEAR \ set LCD cursor at home
17938 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17939 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17940 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17941 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17942 HI2LO \ -- switch from FORTH to assembler
17943 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17944 MOV @PSP+,TOS \ -- TOS
17946 MOV @RSP+,SR \ restore SR flags
17947 BIC #%1111_1000,SR \ but force CPU Active Mode
17948 RET \ (instead of RETI)
17952 \ ------------------------------\
17953 HDNCODE STOP_R2L \ define new STOP_APP
17954 \ ------------------------------\
17955 CMP #RET_ADR,&{RC5TOLCD}+8 \
17956 0<> IF \ if previous START executing
17957 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
17958 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
17959 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
17960 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
17961 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
17962 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
17963 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
17964 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
17965 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
17966 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
17971 \ ------------------------------\
17973 \ ------------------------------\
17974 BW1 \ <-- INI_R2L for some events
17976 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17978 ." RC5toLCD is removed,"
17979 ." type START to restart"
17982 \ ------------------------------\
17984 \ ------------------------------\
17985 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
17986 \ ------------------------------\
17988 \ ------------------------------\
17989 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
17990 \ ------------------------------\
17991 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
17992 \ ------------------------------\
17993 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
17994 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
17996 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
17997 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
17999 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
18000 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
18001 \ CMP #4,TOS \ hardware RST
18002 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
18003 \ CMP #2,TOS \ Power_ON event
18004 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
18006 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
18008 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
18010 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
18011 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
18012 \ ------------------------------\
18013 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
18014 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18015 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18016 \ -- \ID input divider \ 10 = /4
18017 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
18018 \ - \TBCLR TimerB Clear
18021 \ -------------------------------\
18022 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18023 \ -- \CM Capture Mode
18028 \ --- \OUTMOD \ 011 = set/reset
18034 \ -------------------------------\
18036 \ -------------------------------\
18038 \ ------------------------------\
18039 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
18040 \ ------------------------------\
18041 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
18042 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
18043 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
18044 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
18046 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
18047 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
18049 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
18050 \ ------------------------------\
18051 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
18052 \ ------------------------------\
18053 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
18054 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
18055 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18056 \ ------------------------------\
18057 BIS.B #LCDVo,&LCDVo_DIR \
18058 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
18059 \ ------------------------------\
18060 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18061 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18062 \ ------------------------------\
18063 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18064 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18065 \ ******************************\
18067 \ ******************************\
18068 BIS.B #RC5,&IR_IE \ enable RC5_Int
18069 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18070 \ ******************************\
18071 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
18072 \ ******************************\
18073 \ %01 0001 0100 \ TAxCTL
18074 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
18075 \ -- \ ID divided by 1
18076 \ -- \ MC MODE = up to TAxCCRn
18077 \ - \ TACLR clear timer count
18080 \ ------------------------------\
18081 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
18082 \ ------------------------------\
18084 \ --- \ TAIDEX pre divisor
18085 \ ------------------------------\
18086 \ %0000 0000 0000 0101 \ TAxCCR0
18087 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
18088 \ ------------------------------\
18089 \ %0000 0000 0001 0000 \ TAxCCTL0
18090 \ - \ CAP capture/compare mode = compare
18093 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
18094 \ ------------------------------\
18095 \ define LPM mode for ACCEPT \
18096 \ ------------------------------\
18097 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
18098 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18099 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18100 \ ------------------------------\
18102 \ ------------------------------\
18104 \ ------------------------------\
18105 #1000 20_US \ 1- wait 20 ms
18106 %011 TOP_LCD \ 2- send DB5=DB4=1
18107 #205 20_US \ 3- wait 4,1 ms
18108 %011 TOP_LCD \ 4- send again DB5=DB4=1
18109 #5 20_US \ 5- wait 0,1 ms
18110 %011 TOP_LCD \ 6- send again again DB5=DB4=1
18111 #2 20_US \ wait 40 us = LCD cycle
18112 %010 TOP_LCD \ 7- send DB5=1 DB4=0
18113 #2 20_US \ wait 40 us = LCD cycle
18114 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18115 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18116 LCD_CLEAR \ 10- "LCD_Clear"
18117 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18118 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18119 LCD_CLEAR \ 10- "LCD_Clear"
18120 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18121 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18122 CR ." I love you" \ display message on LCD
18123 ['] CR >BODY IS CR \ CR executes its default value
18124 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
18125 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
18128 \ ------------------------------\
18130 \ ------------------------------\
18131 CODE START \ this routine replaces WARM and COLD default values by these of this application.
18132 \ ------------------------------\
18133 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
18134 0= IF \ if not done, customizes MARKER_DOES
18135 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
18136 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
18137 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
18138 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
18139 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
18140 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
18141 MOV #RC5_INT,&IR_VEC \ init interrupt vector
18142 MOV #INI_R2L,PC \ then execute new INI_APP, without return
18146 \ ------------------------------\
18149 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
18151 MARKER {RC5TOLCD} \ restore the state before MARKER definition
18152 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
18153 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
18154 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
18155 \ {RC5TOLCD}+14: make room to save previous IR_VEC
18157 [UNDEFINED] CONSTANT [IF]
18158 \ https://forth-standard.org/standard/core/CONSTANT
18159 \ CONSTANT <name> n -- define a Forth CONSTANT
18163 MOV TOS,-2(W) \ PFA = n
18170 [UNDEFINED] STATE [IF]
18171 \ https://forth-standard.org/standard/core/STATE
18172 \ STATE -- a-addr holds compiler state
18173 STATEADR CONSTANT STATE
18177 \ https://forth-standard.org/standard/core/Equal
18178 \ = x1 x2 -- flag test x1=x2
18185 XOR #-1,TOS \ 1 flag Z = 1
18190 [UNDEFINED] IF [IF] \ define IF and THEN
18191 \ https://forth-standard.org/standard/core/IF
18192 \ IF -- IFadr initialize conditional forward branch
18193 CODE IF \ immediate
18196 MOV &DP,TOS \ -- HERE
18197 ADD #4,&DP \ compile one word, reserve one word
18198 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
18199 ADD #2,TOS \ -- HERE+2=IFadr
18203 \ https://forth-standard.org/standard/core/THEN
18204 \ THEN IFadr -- resolve forward branch
18205 CODE THEN \ immediate
18206 MOV &DP,0(TOS) \ -- IFadr
18212 [UNDEFINED] ELSE [IF]
18213 \ https://forth-standard.org/standard/core/ELSE
18214 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
18215 CODE ELSE \ immediate
18216 ADD #4,&DP \ make room to compile two words
18217 MOV &DP,W \ W=HERE+4
18219 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
18221 MOV W,TOS \ -- ELSEadr
18226 [UNDEFINED] IS [IF] \ define DEFER! and IS
18228 \ https://forth-standard.org/standard/core/DEFERStore
18229 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
18230 CODE DEFER! \ xt2 xt1 --
18231 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
18236 \ https://forth-standard.org/standard/core/IS
18239 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
18240 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
18241 \ or in a definition : ... ['] U. IS DISPLAY ...
18242 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
18244 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
18248 IF POSTPONE ['] POSTPONE DEFER!
18254 [UNDEFINED] >BODY [IF]
18255 \ https://forth-standard.org/standard/core/toBODY
18256 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
18263 \ CODE 20uS \ n -- 8MHz version
18264 \ BEGIN \ 4 + 16 ~ loop
18265 \ MOV #39,rDOCON \ 39
18272 \ MOV #XDOCON,rDOCON \ 2
18277 CODE 20_US \ n -- n * 20 us
18278 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18280 BIT #1,&LCD_TIM_CTL \ 3
18281 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18282 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18284 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18289 CODE TOP_LCD \ LCD Sample
18290 \ \ if write : %xxxx_WWWW --
18291 \ \ if read : -- %0000_RRRR
18292 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18293 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18294 0= IF \ write LCD bits pattern
18295 AND.B #LCD_DB,TOS \
18296 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18297 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18300 THEN \ read LCD bits pattern
18303 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18304 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18305 AND.B #LCD_DB,TOS \
18309 CODE LCD_WRC \ char -- Write Char
18310 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18312 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
18313 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
18314 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18315 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18316 COLON \ high level word starts here
18317 TOP_LCD 2 20_US \ write high nibble first
18321 CODE LCD_WRF \ func -- Write Fonction
18322 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18326 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18327 : LCD_HOME $02 LCD_WRF 100 20_us ;
18329 \ [UNDEFINED] OR [IF]
18331 \ \ https://forth-standard.org/standard/core/OR
18332 \ \ C OR x1 x2 -- x3 logical OR
18340 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18341 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18342 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18343 \ : LCD_FN_SET $20 OR LCD_WrF ;
18344 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18345 \ : LCD_GOTO $80 OR LCD_WrF ;
18348 \ CODE LCD_RDS \ -- status Read Status
18349 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18350 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18351 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18352 \ COLON \ starts a FORTH word
18353 \ TOP_LCD 2 20_us \ -- %0000_HHHH
18354 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
18355 \ HI2LO \ switch from FORTH to assembler
18356 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
18357 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
18358 \ MOV @RSP+,IP \ restore IP saved by COLON
18362 \ CODE LCD_RDC \ -- char Read Char
18363 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18368 \ ******************************\
18369 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18370 \ ******************************\
18371 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18372 BIT.B #SW2,&SW2_IN \ test switch S2
18373 0= IF \ case of switch S2 pressed
18374 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18376 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18379 BIT.B #SW1,&SW1_IN \ test switch S1 input
18380 0= IF \ case of Switch S1 pressed
18381 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18383 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18390 \ ******************************\
18391 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
18392 \ ******************************\
18393 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18394 \ ******************************\
18395 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18396 \ \ SMclock = 8|16|24 MHz
18397 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18398 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18399 \ \ SR(9)=new Toggle bit memory (ADD on)
18400 \ ******************************\
18401 \ RC5_FirstStartBitHalfCycle: \
18402 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18403 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18404 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18406 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18407 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18409 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18410 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18412 MOV #1778,X \ RC5_Period * 1us
18413 MOV #14,W \ count of loop
18415 \ ******************************\
18416 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18417 \ ******************************\ |
18418 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18419 \ RC5_Compute_3/4_Period: \ |
18420 RRUM #1,X \ X=1/2 cycle |
18423 ADD X,Y \ Y=3/4 cycle
18424 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18426 \ ******************************\
18427 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18428 \ ******************************\
18429 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18430 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18431 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18432 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18433 SUB #1,W \ decrement count loop
18434 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18435 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18436 0<> WHILE \ ----> out of loop ----+
18437 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18439 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18440 CMP Y,X \ 1 | cycle time out of bound ?
18441 U>= IF \ 2 ^ | yes:
18442 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18443 GOTO FW1 \ | | quit on truncated RC5 message
18445 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18447 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18448 \ ******************************\ |
18449 \ RC5_SampleEndOf: \ <---------------------+
18450 \ ******************************\
18451 BIC #$30,&RC5_TIM_CTL \ stop timer
18452 \ ******************************\
18453 \ RC5_ComputeNewRC5word \
18454 \ ******************************\
18455 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
18456 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
18457 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
18458 \ ******************************\
18459 \ RC5_ComputeC6bit \
18460 \ ******************************\
18461 BIT #BIT14,T \ test /C6 bit in T
18462 0= IF BIS #BIT6,X \ set C6 bit in X
18463 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
18464 \ ******************************\
18465 \ RC5_CommandByteIsDone \ -- BASE RC5_code
18466 \ ******************************\
18467 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
18468 \ ******************************\
18469 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
18470 XOR @RSP,T \ (new XOR old) Toggle bits
18471 BIT #UF10,T \ repeated RC5_command ?
18472 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
18473 XOR #UF10,0(RSP) \ 5 toggle bit memory
18474 \ ******************************\
18475 \ Display IR_RC5 code \
18476 \ ******************************\
18477 SUB #8,PSP \ TOS -- x x x x TOS
18478 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
18479 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
18480 MOV #$10,&BASEADR \ set hexadecimal base
18481 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
18482 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
18483 LO2HI \ switch from assembler to FORTH
18484 LCD_CLEAR \ set LCD cursor at home
18485 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
18486 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
18487 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
18488 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
18489 HI2LO \ -- switch from FORTH to assembler
18490 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
18491 MOV @PSP+,TOS \ -- TOS
18493 MOV @RSP+,SR \ restore SR flags
18494 BIC #%1111_1000,SR \ but force CPU Active Mode
18495 RET \ (instead of RETI)
18499 \ ------------------------------\
18500 HDNCODE STOP_R2L \ define new STOP_APP
18501 \ ------------------------------\
18502 CMP #RET_ADR,&{RC5TOLCD}+8 \
18503 0<> IF \ if previous START executing
18504 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
18505 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
18506 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
18507 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
18508 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
18509 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
18510 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
18511 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
18512 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
18513 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
18518 \ ------------------------------\
18520 \ ------------------------------\
18521 BW1 \ <-- INI_R2L for some events
18523 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
18525 ." RC5toLCD is removed,"
18526 ." type START to restart"
18529 \ ------------------------------\
18531 \ ------------------------------\
18532 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
18533 \ ------------------------------\
18535 \ ------------------------------\
18536 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
18537 \ ------------------------------\
18538 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
18539 \ ------------------------------\
18540 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
18541 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
18543 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
18544 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
18546 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
18547 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
18548 \ CMP #4,TOS \ hardware RST
18549 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
18550 \ CMP #2,TOS \ Power_ON event
18551 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
18553 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
18555 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
18557 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
18558 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
18559 \ ------------------------------\
18560 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
18561 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18562 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18563 \ -- \ID input divider \ 10 = /4
18564 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
18565 \ - \TBCLR TimerB Clear
18568 \ -------------------------------\
18569 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18570 \ -- \CM Capture Mode
18575 \ --- \OUTMOD \ 011 = set/reset
18581 \ -------------------------------\
18583 \ -------------------------------\
18585 \ ------------------------------\
18586 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
18587 \ ------------------------------\
18588 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
18589 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
18590 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
18591 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
18593 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
18594 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
18596 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
18597 \ ------------------------------\
18598 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
18599 \ ------------------------------\
18600 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
18601 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
18602 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18603 \ ------------------------------\
18604 BIS.B #LCDVo,&LCDVo_DIR \
18605 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
18606 \ ------------------------------\
18607 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18608 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18609 \ ------------------------------\
18610 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18611 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18612 \ ******************************\
18614 \ ******************************\
18615 BIS.B #RC5,&IR_IE \ enable RC5_Int
18616 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18617 \ ******************************\
18618 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
18619 \ ******************************\
18620 \ %01 0001 0100 \ TAxCTL
18621 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
18622 \ -- \ ID divided by 1
18623 \ -- \ MC MODE = up to TAxCCRn
18624 \ - \ TACLR clear timer count
18627 \ ------------------------------\
18628 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
18629 \ ------------------------------\
18631 \ --- \ TAIDEX pre divisor
18632 \ ------------------------------\
18633 \ %0000 0000 0000 0101 \ TAxCCR0
18634 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
18635 \ ------------------------------\
18636 \ %0000 0000 0001 0000 \ TAxCCTL0
18637 \ - \ CAP capture/compare mode = compare
18640 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
18641 \ ------------------------------\
18642 \ define LPM mode for ACCEPT \
18643 \ ------------------------------\
18644 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
18645 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18646 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18647 \ ------------------------------\
18649 \ ------------------------------\
18651 \ ------------------------------\
18652 #1000 20_US \ 1- wait 20 ms
18653 %011 TOP_LCD \ 2- send DB5=DB4=1
18654 #205 20_US \ 3- wait 4,1 ms
18655 %011 TOP_LCD \ 4- send again DB5=DB4=1
18656 #5 20_US \ 5- wait 0,1 ms
18657 %011 TOP_LCD \ 6- send again again DB5=DB4=1
18658 #2 20_US \ wait 40 us = LCD cycle
18659 %010 TOP_LCD \ 7- send DB5=1 DB4=0
18660 #2 20_US \ wait 40 us = LCD cycle
18661 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18662 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18663 LCD_CLEAR \ 10- "LCD_Clear"
18664 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18665 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18666 LCD_CLEAR \ 10- "LCD_Clear"
18667 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18668 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18669 CR ." I love you" \ display message on LCD
18670 ['] CR >BODY IS CR \ CR executes its default value
18671 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
18672 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
18675 \ ------------------------------\
18677 \ ------------------------------\
18678 CODE START \ this routine replaces WARM and COLD default values by these of this application.
18679 \ ------------------------------\
18680 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
18681 0= IF \ if not done, customizes MARKER_DOES
18682 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
18683 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
18684 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
18685 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
18686 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
18687 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
18688 MOV #RC5_INT,&IR_VEC \ init interrupt vector
18689 MOV #INI_R2L,PC \ then execute new INI_APP, without return
18693 \ ------------------------------\
18696 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
18698 MARKER {RC5TOLCD} \ restore the state before MARKER definition
18699 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
18700 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
18701 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
18702 \ {RC5TOLCD}+14: make room to save previous IR_VEC
18704 [UNDEFINED] CONSTANT [IF]
18705 \ https://forth-standard.org/standard/core/CONSTANT
18706 \ CONSTANT <name> n -- define a Forth CONSTANT
18710 MOV TOS,-2(W) \ PFA = n
18717 [UNDEFINED] STATE [IF]
18718 \ https://forth-standard.org/standard/core/STATE
18719 \ STATE -- a-addr holds compiler state
18720 STATEADR CONSTANT STATE
18724 \ https://forth-standard.org/standard/core/Equal
18725 \ = x1 x2 -- flag test x1=x2
18732 XOR #-1,TOS \ 1 flag Z = 1
18737 [UNDEFINED] IF [IF] \ define IF and THEN
18738 \ https://forth-standard.org/standard/core/IF
18739 \ IF -- IFadr initialize conditional forward branch
18740 CODE IF \ immediate
18743 MOV &DP,TOS \ -- HERE
18744 ADD #4,&DP \ compile one word, reserve one word
18745 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
18746 ADD #2,TOS \ -- HERE+2=IFadr
18750 \ https://forth-standard.org/standard/core/THEN
18751 \ THEN IFadr -- resolve forward branch
18752 CODE THEN \ immediate
18753 MOV &DP,0(TOS) \ -- IFadr
18759 [UNDEFINED] ELSE [IF]
18760 \ https://forth-standard.org/standard/core/ELSE
18761 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
18762 CODE ELSE \ immediate
18763 ADD #4,&DP \ make room to compile two words
18764 MOV &DP,W \ W=HERE+4
18766 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
18768 MOV W,TOS \ -- ELSEadr
18773 [UNDEFINED] IS [IF] \ define DEFER! and IS
18775 \ https://forth-standard.org/standard/core/DEFERStore
18776 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
18777 CODE DEFER! \ xt2 xt1 --
18778 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
18783 \ https://forth-standard.org/standard/core/IS
18786 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
18787 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
18788 \ or in a definition : ... ['] U. IS DISPLAY ...
18789 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
18791 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
18795 IF POSTPONE ['] POSTPONE DEFER!
18801 [UNDEFINED] >BODY [IF]
18802 \ https://forth-standard.org/standard/core/toBODY
18803 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
18810 \ CODE 20uS \ n -- 8MHz version
18811 \ BEGIN \ 4 + 16 ~ loop
18812 \ MOV #39,rDOCON \ 39
18819 \ MOV #XDOCON,rDOCON \ 2
18824 CODE 20_US \ n -- n * 20 us
18825 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18827 BIT #1,&LCD_TIM_CTL \ 3
18828 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18829 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18831 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18836 CODE TOP_LCD \ LCD Sample
18837 \ \ if write : %xxxx_WWWW --
18838 \ \ if read : -- %0000_RRRR
18839 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18840 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18841 0= IF \ write LCD bits pattern
18842 AND.B #LCD_DB,TOS \
18843 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18844 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18847 THEN \ read LCD bits pattern
18850 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18851 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18852 AND.B #LCD_DB,TOS \
18856 CODE LCD_WRC \ char -- Write Char
18857 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18859 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
18860 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
18861 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18862 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18863 COLON \ high level word starts here
18864 TOP_LCD 2 20_US \ write high nibble first
18868 CODE LCD_WRF \ func -- Write Fonction
18869 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18873 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18874 : LCD_HOME $02 LCD_WRF 100 20_us ;
18876 \ [UNDEFINED] OR [IF]
18878 \ \ https://forth-standard.org/standard/core/OR
18879 \ \ C OR x1 x2 -- x3 logical OR
18887 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18888 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18889 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18890 \ : LCD_FN_SET $20 OR LCD_WrF ;
18891 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18892 \ : LCD_GOTO $80 OR LCD_WrF ;
18895 \ CODE LCD_RDS \ -- status Read Status
18896 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18897 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18898 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18899 \ COLON \ starts a FORTH word
18900 \ TOP_LCD 2 20_us \ -- %0000_HHHH
18901 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
18902 \ HI2LO \ switch from FORTH to assembler
18903 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
18904 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
18905 \ MOV @RSP+,IP \ restore IP saved by COLON
18909 \ CODE LCD_RDC \ -- char Read Char
18910 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18915 \ ******************************\
18916 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18917 \ ******************************\
18918 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18919 BIT.B #SW2,&SW2_IN \ test switch S2
18920 0= IF \ case of switch S2 pressed
18921 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18923 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18926 BIT.B #SW1,&SW1_IN \ test switch S1 input
18927 0= IF \ case of Switch S1 pressed
18928 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18930 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18937 \ ******************************\
18938 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
18939 \ ******************************\
18940 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18941 \ ******************************\
18942 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18943 \ \ SMclock = 8|16|24 MHz
18944 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18945 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18946 \ \ SR(9)=new Toggle bit memory (ADD on)
18947 \ ******************************\
18948 \ RC5_FirstStartBitHalfCycle: \
18949 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18950 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18951 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18953 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18954 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18956 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18957 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18959 MOV #1778,X \ RC5_Period * 1us
18960 MOV #14,W \ count of loop
18962 \ ******************************\
18963 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18964 \ ******************************\ |
18965 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18966 \ RC5_Compute_3/4_Period: \ |
18967 RRUM #1,X \ X=1/2 cycle |
18970 ADD X,Y \ Y=3/4 cycle
18971 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18973 \ ******************************\
18974 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18975 \ ******************************\
18976 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18977 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18978 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18979 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18980 SUB #1,W \ decrement count loop
18981 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18982 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18983 0<> WHILE \ ----> out of loop ----+
18984 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18986 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18987 CMP Y,X \ 1 | cycle time out of bound ?
18988 U>= IF \ 2 ^ | yes:
18989 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18990 GOTO FW1 \ | | quit on truncated RC5 message
18992 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18994 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18995 \ ******************************\ |
18996 \ RC5_SampleEndOf: \ <---------------------+
18997 \ ******************************\
18998 BIC #$30,&RC5_TIM_CTL \ stop timer
18999 \ ******************************\
19000 \ RC5_ComputeNewRC5word \
19001 \ ******************************\
19002 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
19003 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
19004 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
19005 \ ******************************\
19006 \ RC5_ComputeC6bit \
19007 \ ******************************\
19008 BIT #BIT14,T \ test /C6 bit in T
19009 0= IF BIS #BIT6,X \ set C6 bit in X
19010 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
19011 \ ******************************\
19012 \ RC5_CommandByteIsDone \ -- BASE RC5_code
19013 \ ******************************\
19014 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
19015 \ ******************************\
19016 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
19017 XOR @RSP,T \ (new XOR old) Toggle bits
19018 BIT #UF10,T \ repeated RC5_command ?
19019 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
19020 XOR #UF10,0(RSP) \ 5 toggle bit memory
19021 \ ******************************\
19022 \ Display IR_RC5 code \
19023 \ ******************************\
19024 SUB #8,PSP \ TOS -- x x x x TOS
19025 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19026 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19027 MOV #$10,&BASEADR \ set hexadecimal base
19028 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19029 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19030 LO2HI \ switch from assembler to FORTH
19031 LCD_CLEAR \ set LCD cursor at home
19032 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19033 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19034 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19035 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19036 HI2LO \ -- switch from FORTH to assembler
19037 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19038 MOV @PSP+,TOS \ -- TOS
19040 MOV @RSP+,SR \ restore SR flags
19041 BIC #%1111_1000,SR \ but force CPU Active Mode
19042 RET \ (instead of RETI)
19046 \ ------------------------------\
19047 HDNCODE STOP_R2L \ define new STOP_APP
19048 \ ------------------------------\
19049 CMP #RET_ADR,&{RC5TOLCD}+8 \
19050 0<> IF \ if previous START executing
19051 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
19052 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
19053 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
19054 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
19055 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
19056 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
19057 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
19058 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
19059 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
19060 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
19065 \ ------------------------------\
19067 \ ------------------------------\
19068 BW1 \ <-- INI_R2L for some events
19070 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19072 ." RC5toLCD is removed,"
19073 ." type START to restart"
19076 \ ------------------------------\
19078 \ ------------------------------\
19079 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
19080 \ ------------------------------\
19082 \ ------------------------------\
19083 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
19084 \ ------------------------------\
19085 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
19086 \ ------------------------------\
19087 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
19088 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
19090 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
19091 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
19093 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
19094 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
19095 \ CMP #4,TOS \ hardware RST
19096 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
19097 \ CMP #2,TOS \ Power_ON event
19098 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19100 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
19102 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
19104 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
19105 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
19106 \ ------------------------------\
19107 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19108 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19109 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19110 \ -- \ID input divider \ 10 = /4
19111 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19112 \ - \TBCLR TimerB Clear
19115 \ -------------------------------\
19116 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19117 \ -- \CM Capture Mode
19122 \ --- \OUTMOD \ 011 = set/reset
19128 \ -------------------------------\
19130 \ -------------------------------\
19132 \ ------------------------------\
19133 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19134 \ ------------------------------\
19135 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19136 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19137 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19138 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19140 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19141 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19143 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19144 \ ------------------------------\
19145 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19146 \ ------------------------------\
19147 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19148 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19149 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19150 \ ------------------------------\
19151 BIS.B #LCDVo,&LCDVo_DIR \
19152 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19153 \ ------------------------------\
19154 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19155 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19156 \ ------------------------------\
19157 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19158 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19159 \ ******************************\
19161 \ ******************************\
19162 BIS.B #RC5,&IR_IE \ enable RC5_Int
19163 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19164 \ ******************************\
19165 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19166 \ ******************************\
19167 \ %01 0001 0100 \ TAxCTL
19168 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19169 \ -- \ ID divided by 1
19170 \ -- \ MC MODE = up to TAxCCRn
19171 \ - \ TACLR clear timer count
19174 \ ------------------------------\
19175 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19176 \ ------------------------------\
19178 \ --- \ TAIDEX pre divisor
19179 \ ------------------------------\
19180 \ %0000 0000 0000 0101 \ TAxCCR0
19181 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19182 \ ------------------------------\
19183 \ %0000 0000 0001 0000 \ TAxCCTL0
19184 \ - \ CAP capture/compare mode = compare
19187 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19188 \ ------------------------------\
19189 \ define LPM mode for ACCEPT \
19190 \ ------------------------------\
19191 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
19192 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19193 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19194 \ ------------------------------\
19196 \ ------------------------------\
19198 \ ------------------------------\
19199 #1000 20_US \ 1- wait 20 ms
19200 %011 TOP_LCD \ 2- send DB5=DB4=1
19201 #205 20_US \ 3- wait 4,1 ms
19202 %011 TOP_LCD \ 4- send again DB5=DB4=1
19203 #5 20_US \ 5- wait 0,1 ms
19204 %011 TOP_LCD \ 6- send again again DB5=DB4=1
19205 #2 20_US \ wait 40 us = LCD cycle
19206 %010 TOP_LCD \ 7- send DB5=1 DB4=0
19207 #2 20_US \ wait 40 us = LCD cycle
19208 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19209 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19210 LCD_CLEAR \ 10- "LCD_Clear"
19211 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19212 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19213 LCD_CLEAR \ 10- "LCD_Clear"
19214 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19215 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19216 CR ." I love you" \ display message on LCD
19217 ['] CR >BODY IS CR \ CR executes its default value
19218 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
19219 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19222 \ ------------------------------\
19224 \ ------------------------------\
19225 CODE START \ this routine replaces WARM and COLD default values by these of this application.
19226 \ ------------------------------\
19227 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
19228 0= IF \ if not done, customizes MARKER_DOES
19229 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
19230 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
19231 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
19232 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
19233 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19234 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
19235 MOV #RC5_INT,&IR_VEC \ init interrupt vector
19236 MOV #INI_R2L,PC \ then execute new INI_APP, without return
19240 \ ------------------------------\
19243 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
19245 MARKER {RC5TOLCD} \ restore the state before MARKER definition
19246 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
19247 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
19248 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
19249 \ {RC5TOLCD}+14: make room to save previous IR_VEC
19251 [UNDEFINED] CONSTANT [IF]
19252 \ https://forth-standard.org/standard/core/CONSTANT
19253 \ CONSTANT <name> n -- define a Forth CONSTANT
19257 MOV TOS,-2(W) \ PFA = n
19264 [UNDEFINED] STATE [IF]
19265 \ https://forth-standard.org/standard/core/STATE
19266 \ STATE -- a-addr holds compiler state
19267 STATEADR CONSTANT STATE
19271 \ https://forth-standard.org/standard/core/Equal
19272 \ = x1 x2 -- flag test x1=x2
19279 XOR #-1,TOS \ 1 flag Z = 1
19284 [UNDEFINED] IF [IF] \ define IF and THEN
19285 \ https://forth-standard.org/standard/core/IF
19286 \ IF -- IFadr initialize conditional forward branch
19287 CODE IF \ immediate
19290 MOV &DP,TOS \ -- HERE
19291 ADD #4,&DP \ compile one word, reserve one word
19292 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
19293 ADD #2,TOS \ -- HERE+2=IFadr
19297 \ https://forth-standard.org/standard/core/THEN
19298 \ THEN IFadr -- resolve forward branch
19299 CODE THEN \ immediate
19300 MOV &DP,0(TOS) \ -- IFadr
19306 [UNDEFINED] ELSE [IF]
19307 \ https://forth-standard.org/standard/core/ELSE
19308 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
19309 CODE ELSE \ immediate
19310 ADD #4,&DP \ make room to compile two words
19311 MOV &DP,W \ W=HERE+4
19313 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
19315 MOV W,TOS \ -- ELSEadr
19320 [UNDEFINED] IS [IF] \ define DEFER! and IS
19322 \ https://forth-standard.org/standard/core/DEFERStore
19323 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
19324 CODE DEFER! \ xt2 xt1 --
19325 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
19330 \ https://forth-standard.org/standard/core/IS
19333 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
19334 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
19335 \ or in a definition : ... ['] U. IS DISPLAY ...
19336 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
19338 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
19342 IF POSTPONE ['] POSTPONE DEFER!
19348 [UNDEFINED] >BODY [IF]
19349 \ https://forth-standard.org/standard/core/toBODY
19350 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
19357 \ CODE 20uS \ n -- 8MHz version
19358 \ BEGIN \ 4 + 16 ~ loop
19359 \ MOV #39,rDOCON \ 39
19366 \ MOV #XDOCON,rDOCON \ 2
19371 CODE 20_US \ n -- n * 20 us
19372 BEGIN \ here we presume that LCD_TIM_IFG = 1...
19374 BIT #1,&LCD_TIM_CTL \ 3
19375 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
19376 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
19378 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
19383 CODE TOP_LCD \ LCD Sample
19384 \ \ if write : %xxxx_WWWW --
19385 \ \ if read : -- %0000_RRRR
19386 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19387 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19388 0= IF \ write LCD bits pattern
19389 AND.B #LCD_DB,TOS \
19390 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19391 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19394 THEN \ read LCD bits pattern
19397 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19398 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19399 AND.B #LCD_DB,TOS \
19403 CODE LCD_WRC \ char -- Write Char
19404 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19406 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
19407 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
19408 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19409 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19410 COLON \ high level word starts here
19411 TOP_LCD 2 20_US \ write high nibble first
19415 CODE LCD_WRF \ func -- Write Fonction
19416 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19420 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
19421 : LCD_HOME $02 LCD_WRF 100 20_us ;
19423 \ [UNDEFINED] OR [IF]
19425 \ \ https://forth-standard.org/standard/core/OR
19426 \ \ C OR x1 x2 -- x3 logical OR
19434 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
19435 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
19436 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
19437 \ : LCD_FN_SET $20 OR LCD_WrF ;
19438 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
19439 \ : LCD_GOTO $80 OR LCD_WrF ;
19442 \ CODE LCD_RDS \ -- status Read Status
19443 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19444 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19445 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19446 \ COLON \ starts a FORTH word
19447 \ TOP_LCD 2 20_us \ -- %0000_HHHH
19448 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
19449 \ HI2LO \ switch from FORTH to assembler
19450 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
19451 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
19452 \ MOV @RSP+,IP \ restore IP saved by COLON
19456 \ CODE LCD_RDC \ -- char Read Char
19457 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19462 \ ******************************\
19463 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19464 \ ******************************\
19465 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
19466 BIT.B #SW2,&SW2_IN \ test switch S2
19467 0= IF \ case of switch S2 pressed
19468 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
19470 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
19473 BIT.B #SW1,&SW1_IN \ test switch S1 input
19474 0= IF \ case of Switch S1 pressed
19475 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
19477 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
19484 \ ******************************\
19485 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
19486 \ ******************************\
19487 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19488 \ ******************************\
19489 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19490 \ \ SMclock = 8|16|24 MHz
19491 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
19492 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
19493 \ \ SR(9)=new Toggle bit memory (ADD on)
19494 \ ******************************\
19495 \ RC5_FirstStartBitHalfCycle: \
19496 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
19497 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
19498 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
19500 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
19501 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
19503 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
19504 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
19506 MOV #1778,X \ RC5_Period * 1us
19507 MOV #14,W \ count of loop
19509 \ ******************************\
19510 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
19511 \ ******************************\ |
19512 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
19513 \ RC5_Compute_3/4_Period: \ |
19514 RRUM #1,X \ X=1/2 cycle |
19517 ADD X,Y \ Y=3/4 cycle
19518 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
19520 \ ******************************\
19521 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
19522 \ ******************************\
19523 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19524 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
19525 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19526 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19527 SUB #1,W \ decrement count loop
19528 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
19529 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19530 0<> WHILE \ ----> out of loop ----+
19531 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
19533 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
19534 CMP Y,X \ 1 | cycle time out of bound ?
19535 U>= IF \ 2 ^ | yes:
19536 BIC #$30,&RC5_TIM_CTL \ | | stop timer
19537 GOTO FW1 \ | | quit on truncated RC5 message
19539 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
19541 REPEAT \ ----> loop back --+ | with X = new RC5_period value
19542 \ ******************************\ |
19543 \ RC5_SampleEndOf: \ <---------------------+
19544 \ ******************************\
19545 BIC #$30,&RC5_TIM_CTL \ stop timer
19546 \ ******************************\
19547 \ RC5_ComputeNewRC5word \
19548 \ ******************************\
19549 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
19550 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
19551 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
19552 \ ******************************\
19553 \ RC5_ComputeC6bit \
19554 \ ******************************\
19555 BIT #BIT14,T \ test /C6 bit in T
19556 0= IF BIS #BIT6,X \ set C6 bit in X
19557 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
19558 \ ******************************\
19559 \ RC5_CommandByteIsDone \ -- BASE RC5_code
19560 \ ******************************\
19561 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
19562 \ ******************************\
19563 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
19564 XOR @RSP,T \ (new XOR old) Toggle bits
19565 BIT #UF10,T \ repeated RC5_command ?
19566 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
19567 XOR #UF10,0(RSP) \ 5 toggle bit memory
19568 \ ******************************\
19569 \ Display IR_RC5 code \
19570 \ ******************************\
19571 SUB #8,PSP \ TOS -- x x x x TOS
19572 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19573 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19574 MOV #$10,&BASEADR \ set hexadecimal base
19575 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19576 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19577 LO2HI \ switch from assembler to FORTH
19578 LCD_CLEAR \ set LCD cursor at home
19579 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19580 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19581 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19582 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19583 HI2LO \ -- switch from FORTH to assembler
19584 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19585 MOV @PSP+,TOS \ -- TOS
19587 MOV @RSP+,SR \ restore SR flags
19588 BIC #%1111_1000,SR \ but force CPU Active Mode
19589 RET \ (instead of RETI)
19593 \ ------------------------------\
19594 HDNCODE STOP_R2L \ define new STOP_APP
19595 \ ------------------------------\
19596 CMP #RET_ADR,&{RC5TOLCD}+8 \
19597 0<> IF \ if previous START executing
19598 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
19599 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
19600 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
19601 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
19602 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
19603 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
19604 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
19605 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
19606 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
19607 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
19612 \ ------------------------------\
19614 \ ------------------------------\
19615 BW1 \ <-- INI_R2L for some events
19617 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19619 ." RC5toLCD is removed,"
19620 ." type START to restart"
19623 \ ------------------------------\
19625 \ ------------------------------\
19626 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
19627 \ ------------------------------\
19629 \ ------------------------------\
19630 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
19631 \ ------------------------------\
19632 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
19633 \ ------------------------------\
19634 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
19635 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
19637 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
19638 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
19640 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
19641 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
19642 \ CMP #4,TOS \ hardware RST
19643 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
19644 \ CMP #2,TOS \ Power_ON event
19645 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19647 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
19649 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
19651 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
19652 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
19653 \ ------------------------------\
19654 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19655 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19656 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19657 \ -- \ID input divider \ 10 = /4
19658 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19659 \ - \TBCLR TimerB Clear
19662 \ -------------------------------\
19663 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19664 \ -- \CM Capture Mode
19669 \ --- \OUTMOD \ 011 = set/reset
19675 \ -------------------------------\
19677 \ -------------------------------\
19679 \ ------------------------------\
19680 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19681 \ ------------------------------\
19682 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19683 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19684 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19685 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19687 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19688 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19690 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19691 \ ------------------------------\
19692 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19693 \ ------------------------------\
19694 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19695 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19696 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19697 \ ------------------------------\
19698 BIS.B #LCDVo,&LCDVo_DIR \
19699 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19700 \ ------------------------------\
19701 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19702 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19703 \ ------------------------------\
19704 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19705 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19706 \ ******************************\
19708 \ ******************************\
19709 BIS.B #RC5,&IR_IE \ enable RC5_Int
19710 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19711 \ ******************************\
19712 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19713 \ ******************************\
19714 \ %01 0001 0100 \ TAxCTL
19715 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19716 \ -- \ ID divided by 1
19717 \ -- \ MC MODE = up to TAxCCRn
19718 \ - \ TACLR clear timer count
19721 \ ------------------------------\
19722 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19723 \ ------------------------------\
19725 \ --- \ TAIDEX pre divisor
19726 \ ------------------------------\
19727 \ %0000 0000 0000 0101 \ TAxCCR0
19728 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19729 \ ------------------------------\
19730 \ %0000 0000 0001 0000 \ TAxCCTL0
19731 \ - \ CAP capture/compare mode = compare
19734 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19735 \ ------------------------------\
19736 \ define LPM mode for ACCEPT \
19737 \ ------------------------------\
19738 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
19739 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19740 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19741 \ ------------------------------\
19743 \ ------------------------------\
19745 \ ------------------------------\
19746 #1000 20_US \ 1- wait 20 ms
19747 %011 TOP_LCD \ 2- send DB5=DB4=1
19748 #205 20_US \ 3- wait 4,1 ms
19749 %011 TOP_LCD \ 4- send again DB5=DB4=1
19750 #5 20_US \ 5- wait 0,1 ms
19751 %011 TOP_LCD \ 6- send again again DB5=DB4=1
19752 #2 20_US \ wait 40 us = LCD cycle
19753 %010 TOP_LCD \ 7- send DB5=1 DB4=0
19754 #2 20_US \ wait 40 us = LCD cycle
19755 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19756 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19757 LCD_CLEAR \ 10- "LCD_Clear"
19758 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19759 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19760 LCD_CLEAR \ 10- "LCD_Clear"
19761 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19762 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19763 CR ." I love you" \ display message on LCD
19764 ['] CR >BODY IS CR \ CR executes its default value
19765 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
19766 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19769 \ ------------------------------\
19771 \ ------------------------------\
19772 CODE START \ this routine replaces WARM and COLD default values by these of this application.
19773 \ ------------------------------\
19774 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
19775 0= IF \ if not done, customizes MARKER_DOES
19776 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
19777 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
19778 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
19779 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
19780 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19781 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
19782 MOV #RC5_INT,&IR_VEC \ init interrupt vector
19783 MOV #INI_R2L,PC \ then execute new INI_APP, without return
19787 \ ------------------------------\
19790 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
19792 MARKER {RC5TOLCD} \ restore the state before MARKER definition
19793 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
19794 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
19795 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
19796 \ {RC5TOLCD}+14: make room to save previous IR_VEC
19798 [UNDEFINED] CONSTANT [IF]
19799 \ https://forth-standard.org/standard/core/CONSTANT
19800 \ CONSTANT <name> n -- define a Forth CONSTANT
19804 MOV TOS,-2(W) \ PFA = n
19811 [UNDEFINED] STATE [IF]
19812 \ https://forth-standard.org/standard/core/STATE
19813 \ STATE -- a-addr holds compiler state
19814 STATEADR CONSTANT STATE
19818 \ https://forth-standard.org/standard/core/Equal
19819 \ = x1 x2 -- flag test x1=x2
19826 XOR #-1,TOS \ 1 flag Z = 1
19831 [UNDEFINED] IF [IF] \ define IF and THEN
19832 \ https://forth-standard.org/standard/core/IF
19833 \ IF -- IFadr initialize conditional forward branch
19834 CODE IF \ immediate
19837 MOV &DP,TOS \ -- HERE
19838 ADD #4,&DP \ compile one word, reserve one word
19839 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
19840 ADD #2,TOS \ -- HERE+2=IFadr
19844 \ https://forth-standard.org/standard/core/THEN
19845 \ THEN IFadr -- resolve forward branch
19846 CODE THEN \ immediate
19847 MOV &DP,0(TOS) \ -- IFadr
19853 [UNDEFINED] ELSE [IF]
19854 \ https://forth-standard.org/standard/core/ELSE
19855 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
19856 CODE ELSE \ immediate
19857 ADD #4,&DP \ make room to compile two words
19858 MOV &DP,W \ W=HERE+4
19860 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
19862 MOV W,TOS \ -- ELSEadr
19867 [UNDEFINED] IS [IF] \ define DEFER! and IS
19869 \ https://forth-standard.org/standard/core/DEFERStore
19870 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
19871 CODE DEFER! \ xt2 xt1 --
19872 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
19877 \ https://forth-standard.org/standard/core/IS
19880 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
19881 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
19882 \ or in a definition : ... ['] U. IS DISPLAY ...
19883 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
19885 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
19889 IF POSTPONE ['] POSTPONE DEFER!
19895 [UNDEFINED] >BODY [IF]
19896 \ https://forth-standard.org/standard/core/toBODY
19897 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
19904 \ CODE 20uS \ n -- 8MHz version
19905 \ BEGIN \ 4 + 16 ~ loop
19906 \ MOV #39,rDOCON \ 39
19913 \ MOV #XDOCON,rDOCON \ 2
19918 CODE 20_US \ n -- n * 20 us
19919 BEGIN \ here we presume that LCD_TIM_IFG = 1...
19921 BIT #1,&LCD_TIM_CTL \ 3
19922 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
19923 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
19925 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
19930 CODE TOP_LCD \ LCD Sample
19931 \ \ if write : %xxxx_WWWW --
19932 \ \ if read : -- %0000_RRRR
19933 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19934 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19935 0= IF \ write LCD bits pattern
19936 AND.B #LCD_DB,TOS \
19937 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19938 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19941 THEN \ read LCD bits pattern
19944 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19945 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19946 AND.B #LCD_DB,TOS \
19950 CODE LCD_WRC \ char -- Write Char
19951 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19953 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
19954 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
19955 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19956 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19957 COLON \ high level word starts here
19958 TOP_LCD 2 20_US \ write high nibble first
19962 CODE LCD_WRF \ func -- Write Fonction
19963 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19967 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
19968 : LCD_HOME $02 LCD_WRF 100 20_us ;
19970 \ [UNDEFINED] OR [IF]
19972 \ \ https://forth-standard.org/standard/core/OR
19973 \ \ C OR x1 x2 -- x3 logical OR
19981 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
19982 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
19983 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
19984 \ : LCD_FN_SET $20 OR LCD_WrF ;
19985 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
19986 \ : LCD_GOTO $80 OR LCD_WrF ;
19989 \ CODE LCD_RDS \ -- status Read Status
19990 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19991 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19992 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19993 \ COLON \ starts a FORTH word
19994 \ TOP_LCD 2 20_us \ -- %0000_HHHH
19995 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
19996 \ HI2LO \ switch from FORTH to assembler
19997 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
19998 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
19999 \ MOV @RSP+,IP \ restore IP saved by COLON
20003 \ CODE LCD_RDC \ -- char Read Char
20004 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20009 \ ******************************\
20010 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20011 \ ******************************\
20012 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20013 BIT.B #SW2,&SW2_IN \ test switch S2
20014 0= IF \ case of switch S2 pressed
20015 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20017 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20020 BIT.B #SW1,&SW1_IN \ test switch S1 input
20021 0= IF \ case of Switch S1 pressed
20022 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20024 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20031 \ ******************************\
20032 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
20033 \ ******************************\
20034 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20035 \ ******************************\
20036 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20037 \ \ SMclock = 8|16|24 MHz
20038 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20039 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20040 \ \ SR(9)=new Toggle bit memory (ADD on)
20041 \ ******************************\
20042 \ RC5_FirstStartBitHalfCycle: \
20043 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20044 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20045 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20047 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20048 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20050 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20051 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20053 MOV #1778,X \ RC5_Period * 1us
20054 MOV #14,W \ count of loop
20056 \ ******************************\
20057 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
20058 \ ******************************\ |
20059 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20060 \ RC5_Compute_3/4_Period: \ |
20061 RRUM #1,X \ X=1/2 cycle |
20064 ADD X,Y \ Y=3/4 cycle
20065 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
20067 \ ******************************\
20068 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20069 \ ******************************\
20070 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20071 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
20072 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20073 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20074 SUB #1,W \ decrement count loop
20075 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
20076 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20077 0<> WHILE \ ----> out of loop ----+
20078 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20080 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
20081 CMP Y,X \ 1 | cycle time out of bound ?
20082 U>= IF \ 2 ^ | yes:
20083 BIC #$30,&RC5_TIM_CTL \ | | stop timer
20084 GOTO FW1 \ | | quit on truncated RC5 message
20086 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
20088 REPEAT \ ----> loop back --+ | with X = new RC5_period value
20089 \ ******************************\ |
20090 \ RC5_SampleEndOf: \ <---------------------+
20091 \ ******************************\
20092 BIC #$30,&RC5_TIM_CTL \ stop timer
20093 \ ******************************\
20094 \ RC5_ComputeNewRC5word \
20095 \ ******************************\
20096 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
20097 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
20098 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
20099 \ ******************************\
20100 \ RC5_ComputeC6bit \
20101 \ ******************************\
20102 BIT #BIT14,T \ test /C6 bit in T
20103 0= IF BIS #BIT6,X \ set C6 bit in X
20104 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
20105 \ ******************************\
20106 \ RC5_CommandByteIsDone \ -- BASE RC5_code
20107 \ ******************************\
20108 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
20109 \ ******************************\
20110 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
20111 XOR @RSP,T \ (new XOR old) Toggle bits
20112 BIT #UF10,T \ repeated RC5_command ?
20113 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
20114 XOR #UF10,0(RSP) \ 5 toggle bit memory
20115 \ ******************************\
20116 \ Display IR_RC5 code \
20117 \ ******************************\
20118 SUB #8,PSP \ TOS -- x x x x TOS
20119 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
20120 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
20121 MOV #$10,&BASEADR \ set hexadecimal base
20122 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
20123 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
20124 LO2HI \ switch from assembler to FORTH
20125 LCD_CLEAR \ set LCD cursor at home
20126 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
20127 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
20128 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
20129 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
20130 HI2LO \ -- switch from FORTH to assembler
20131 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
20132 MOV @PSP+,TOS \ -- TOS
20134 MOV @RSP+,SR \ restore SR flags
20135 BIC #%1111_1000,SR \ but force CPU Active Mode
20136 RET \ (instead of RETI)
20140 \ ------------------------------\
20141 HDNCODE STOP_R2L \ define new STOP_APP
20142 \ ------------------------------\
20143 CMP #RET_ADR,&{RC5TOLCD}+8 \
20144 0<> IF \ if previous START executing
20145 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
20146 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
20147 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
20148 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
20149 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
20150 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
20151 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
20152 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
20153 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
20154 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
20159 \ ------------------------------\
20161 \ ------------------------------\
20162 BW1 \ <-- INI_R2L for some events
20164 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
20166 ." RC5toLCD is removed,"
20167 ." type START to restart"
20170 \ ------------------------------\
20172 \ ------------------------------\
20173 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
20174 \ ------------------------------\
20176 \ ------------------------------\
20177 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
20178 \ ------------------------------\
20179 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
20180 \ ------------------------------\
20181 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
20182 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
20184 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
20185 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
20187 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
20188 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
20189 \ CMP #4,TOS \ hardware RST
20190 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
20191 \ CMP #2,TOS \ Power_ON event
20192 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
20194 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
20196 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
20198 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
20199 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
20200 \ ------------------------------\
20201 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
20202 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20203 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20204 \ -- \ID input divider \ 10 = /4
20205 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20206 \ - \TBCLR TimerB Clear
20209 \ -------------------------------\
20210 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20211 \ -- \CM Capture Mode
20216 \ --- \OUTMOD \ 011 = set/reset
20222 \ -------------------------------\
20224 \ -------------------------------\
20226 \ ------------------------------\
20227 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20228 \ ------------------------------\
20229 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20230 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20231 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
20232 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20234 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
20235 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20237 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
20238 \ ------------------------------\
20239 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20240 \ ------------------------------\
20241 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
20242 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20243 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20244 \ ------------------------------\
20245 BIS.B #LCDVo,&LCDVo_DIR \
20246 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
20247 \ ------------------------------\
20248 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20249 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20250 \ ------------------------------\
20251 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20252 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20253 \ ******************************\
20255 \ ******************************\
20256 BIS.B #RC5,&IR_IE \ enable RC5_Int
20257 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20258 \ ******************************\
20259 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20260 \ ******************************\
20261 \ %01 0001 0100 \ TAxCTL
20262 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
20263 \ -- \ ID divided by 1
20264 \ -- \ MC MODE = up to TAxCCRn
20265 \ - \ TACLR clear timer count
20268 \ ------------------------------\
20269 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
20270 \ ------------------------------\
20272 \ --- \ TAIDEX pre divisor
20273 \ ------------------------------\
20274 \ %0000 0000 0000 0101 \ TAxCCR0
20275 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20276 \ ------------------------------\
20277 \ %0000 0000 0001 0000 \ TAxCCTL0
20278 \ - \ CAP capture/compare mode = compare
20281 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
20282 \ ------------------------------\
20283 \ define LPM mode for ACCEPT \
20284 \ ------------------------------\
20285 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
20286 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20287 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20288 \ ------------------------------\
20290 \ ------------------------------\
20292 \ ------------------------------\
20293 #1000 20_US \ 1- wait 20 ms
20294 %011 TOP_LCD \ 2- send DB5=DB4=1
20295 #205 20_US \ 3- wait 4,1 ms
20296 %011 TOP_LCD \ 4- send again DB5=DB4=1
20297 #5 20_US \ 5- wait 0,1 ms
20298 %011 TOP_LCD \ 6- send again again DB5=DB4=1
20299 #2 20_US \ wait 40 us = LCD cycle
20300 %010 TOP_LCD \ 7- send DB5=1 DB4=0
20301 #2 20_US \ wait 40 us = LCD cycle
20302 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20303 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20304 LCD_CLEAR \ 10- "LCD_Clear"
20305 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20306 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20307 LCD_CLEAR \ 10- "LCD_Clear"
20308 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20309 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20310 CR ." I love you" \ display message on LCD
20311 ['] CR >BODY IS CR \ CR executes its default value
20312 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
20313 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20316 \ ------------------------------\
20318 \ ------------------------------\
20319 CODE START \ this routine replaces WARM and COLD default values by these of this application.
20320 \ ------------------------------\
20321 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
20322 0= IF \ if not done, customizes MARKER_DOES
20323 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
20324 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
20325 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
20326 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
20327 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
20328 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
20329 MOV #RC5_INT,&IR_VEC \ init interrupt vector
20330 MOV #INI_R2L,PC \ then execute new INI_APP, without return
20334 \ ------------------------------\
20337 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
20339 MARKER {RC5TOLCD} \ restore the state before MARKER definition
20340 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
20341 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
20342 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
20343 \ {RC5TOLCD}+14: make room to save previous IR_VEC
20345 [UNDEFINED] CONSTANT [IF]
20346 \ https://forth-standard.org/standard/core/CONSTANT
20347 \ CONSTANT <name> n -- define a Forth CONSTANT
20351 MOV TOS,-2(W) \ PFA = n
20358 [UNDEFINED] STATE [IF]
20359 \ https://forth-standard.org/standard/core/STATE
20360 \ STATE -- a-addr holds compiler state
20361 STATEADR CONSTANT STATE
20365 \ https://forth-standard.org/standard/core/Equal
20366 \ = x1 x2 -- flag test x1=x2
20373 XOR #-1,TOS \ 1 flag Z = 1
20378 [UNDEFINED] IF [IF] \ define IF and THEN
20379 \ https://forth-standard.org/standard/core/IF
20380 \ IF -- IFadr initialize conditional forward branch
20381 CODE IF \ immediate
20384 MOV &DP,TOS \ -- HERE
20385 ADD #4,&DP \ compile one word, reserve one word
20386 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
20387 ADD #2,TOS \ -- HERE+2=IFadr
20391 \ https://forth-standard.org/standard/core/THEN
20392 \ THEN IFadr -- resolve forward branch
20393 CODE THEN \ immediate
20394 MOV &DP,0(TOS) \ -- IFadr
20400 [UNDEFINED] ELSE [IF]
20401 \ https://forth-standard.org/standard/core/ELSE
20402 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
20403 CODE ELSE \ immediate
20404 ADD #4,&DP \ make room to compile two words
20405 MOV &DP,W \ W=HERE+4
20407 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
20409 MOV W,TOS \ -- ELSEadr
20414 [UNDEFINED] IS [IF] \ define DEFER! and IS
20416 \ https://forth-standard.org/standard/core/DEFERStore
20417 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
20418 CODE DEFER! \ xt2 xt1 --
20419 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
20424 \ https://forth-standard.org/standard/core/IS
20427 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
20428 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
20429 \ or in a definition : ... ['] U. IS DISPLAY ...
20430 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
20432 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
20436 IF POSTPONE ['] POSTPONE DEFER!
20442 [UNDEFINED] >BODY [IF]
20443 \ https://forth-standard.org/standard/core/toBODY
20444 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
20451 \ CODE 20uS \ n -- 8MHz version
20452 \ BEGIN \ 4 + 16 ~ loop
20453 \ MOV #39,rDOCON \ 39
20460 \ MOV #XDOCON,rDOCON \ 2
20465 CODE 20_US \ n -- n * 20 us
20466 BEGIN \ here we presume that LCD_TIM_IFG = 1...
20468 BIT #1,&LCD_TIM_CTL \ 3
20469 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
20470 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
20472 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
20477 CODE TOP_LCD \ LCD Sample
20478 \ \ if write : %xxxx_WWWW --
20479 \ \ if read : -- %0000_RRRR
20480 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20481 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20482 0= IF \ write LCD bits pattern
20483 AND.B #LCD_DB,TOS \
20484 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20485 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20488 THEN \ read LCD bits pattern
20491 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20492 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20493 AND.B #LCD_DB,TOS \
20497 CODE LCD_WRC \ char -- Write Char
20498 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20500 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
20501 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
20502 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20503 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20504 COLON \ high level word starts here
20505 TOP_LCD 2 20_US \ write high nibble first
20509 CODE LCD_WRF \ func -- Write Fonction
20510 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20514 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
20515 : LCD_HOME $02 LCD_WRF 100 20_us ;
20517 \ [UNDEFINED] OR [IF]
20519 \ \ https://forth-standard.org/standard/core/OR
20520 \ \ C OR x1 x2 -- x3 logical OR
20528 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
20529 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
20530 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
20531 \ : LCD_FN_SET $20 OR LCD_WrF ;
20532 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
20533 \ : LCD_GOTO $80 OR LCD_WrF ;
20536 \ CODE LCD_RDS \ -- status Read Status
20537 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20538 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20539 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20540 \ COLON \ starts a FORTH word
20541 \ TOP_LCD 2 20_us \ -- %0000_HHHH
20542 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
20543 \ HI2LO \ switch from FORTH to assembler
20544 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
20545 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
20546 \ MOV @RSP+,IP \ restore IP saved by COLON
20550 \ CODE LCD_RDC \ -- char Read Char
20551 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20556 \ ******************************\
20557 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20558 \ ******************************\
20559 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20560 BIT.B #SW2,&SW2_IN \ test switch S2
20561 0= IF \ case of switch S2 pressed
20562 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20564 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20567 BIT.B #SW1,&SW1_IN \ test switch S1 input
20568 0= IF \ case of Switch S1 pressed
20569 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20571 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20578 \ ******************************\
20579 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
20580 \ ******************************\
20581 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20582 \ ******************************\
20583 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20584 \ \ SMclock = 8|16|24 MHz
20585 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20586 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20587 \ \ SR(9)=new Toggle bit memory (ADD on)
20588 \ ******************************\
20589 \ RC5_FirstStartBitHalfCycle: \
20590 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20591 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20592 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20594 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20595 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20597 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20598 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20600 MOV #1778,X \ RC5_Period * 1us
20601 MOV #14,W \ count of loop
20603 \ ******************************\
20604 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
20605 \ ******************************\ |
20606 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20607 \ RC5_Compute_3/4_Period: \ |
20608 RRUM #1,X \ X=1/2 cycle |
20611 ADD X,Y \ Y=3/4 cycle
20612 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
20614 \ ******************************\
20615 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20616 \ ******************************\
20617 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20618 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
20619 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20620 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20621 SUB #1,W \ decrement count loop
20622 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
20623 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20624 0<> WHILE \ ----> out of loop ----+
20625 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20627 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
20628 CMP Y,X \ 1 | cycle time out of bound ?
20629 U>= IF \ 2 ^ | yes:
20630 BIC #$30,&RC5_TIM_CTL \ | | stop timer
20631 GOTO FW1 \ | | quit on truncated RC5 message
20633 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
20635 REPEAT \ ----> loop back --+ | with X = new RC5_period value
20636 \ ******************************\ |
20637 \ RC5_SampleEndOf: \ <---------------------+
20638 \ ******************************\
20639 BIC #$30,&RC5_TIM_CTL \ stop timer
20640 \ ******************************\
20641 \ RC5_ComputeNewRC5word \
20642 \ ******************************\
20643 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
20644 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
20645 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
20646 \ ******************************\
20647 \ RC5_ComputeC6bit \
20648 \ ******************************\
20649 BIT #BIT14,T \ test /C6 bit in T
20650 0= IF BIS #BIT6,X \ set C6 bit in X
20651 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
20652 \ ******************************\
20653 \ RC5_CommandByteIsDone \ -- BASE RC5_code
20654 \ ******************************\
20655 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
20656 \ ******************************\
20657 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
20658 XOR @RSP,T \ (new XOR old) Toggle bits
20659 BIT #UF10,T \ repeated RC5_command ?
20660 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
20661 XOR #UF10,0(RSP) \ 5 toggle bit memory
20662 \ ******************************\
20663 \ Display IR_RC5 code \
20664 \ ******************************\
20665 SUB #8,PSP \ TOS -- x x x x TOS
20666 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
20667 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
20668 MOV #$10,&BASEADR \ set hexadecimal base
20669 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
20670 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
20671 LO2HI \ switch from assembler to FORTH
20672 LCD_CLEAR \ set LCD cursor at home
20673 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
20674 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
20675 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
20676 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
20677 HI2LO \ -- switch from FORTH to assembler
20678 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
20679 MOV @PSP+,TOS \ -- TOS
20681 MOV @RSP+,SR \ restore SR flags
20682 BIC #%1111_1000,SR \ but force CPU Active Mode
20683 RET \ (instead of RETI)
20687 \ ------------------------------\
20688 HDNCODE STOP_R2L \ define new STOP_APP
20689 \ ------------------------------\
20690 CMP #RET_ADR,&{RC5TOLCD}+8 \
20691 0<> IF \ if previous START executing
20692 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
20693 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
20694 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
20695 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
20696 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
20697 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
20698 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
20699 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
20700 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
20701 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
20706 \ ------------------------------\
20708 \ ------------------------------\
20709 BW1 \ <-- INI_R2L for some events
20711 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
20713 ." RC5toLCD is removed,"
20714 ." type START to restart"
20717 \ ------------------------------\
20719 \ ------------------------------\
20720 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
20721 \ ------------------------------\
20723 \ ------------------------------\
20724 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
20725 \ ------------------------------\
20726 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
20727 \ ------------------------------\
20728 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
20729 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
20731 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
20732 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
20734 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
20735 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
20736 \ CMP #4,TOS \ hardware RST
20737 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
20738 \ CMP #2,TOS \ Power_ON event
20739 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
20741 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
20743 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
20745 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
20746 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
20747 \ ------------------------------\
20748 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
20749 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20750 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20751 \ -- \ID input divider \ 10 = /4
20752 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20753 \ - \TBCLR TimerB Clear
20756 \ -------------------------------\
20757 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20758 \ -- \CM Capture Mode
20763 \ --- \OUTMOD \ 011 = set/reset
20769 \ -------------------------------\
20771 \ -------------------------------\
20773 \ ------------------------------\
20774 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20775 \ ------------------------------\
20776 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20777 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20778 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
20779 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20781 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
20782 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20784 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
20785 \ ------------------------------\
20786 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20787 \ ------------------------------\
20788 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
20789 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20790 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20791 \ ------------------------------\
20792 BIS.B #LCDVo,&LCDVo_DIR \
20793 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
20794 \ ------------------------------\
20795 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20796 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20797 \ ------------------------------\
20798 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20799 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20800 \ ******************************\
20802 \ ******************************\
20803 BIS.B #RC5,&IR_IE \ enable RC5_Int
20804 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20805 \ ******************************\
20806 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20807 \ ******************************\
20808 \ %01 0001 0100 \ TAxCTL
20809 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
20810 \ -- \ ID divided by 1
20811 \ -- \ MC MODE = up to TAxCCRn
20812 \ - \ TACLR clear timer count
20815 \ ------------------------------\
20816 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
20817 \ ------------------------------\
20819 \ --- \ TAIDEX pre divisor
20820 \ ------------------------------\
20821 \ %0000 0000 0000 0101 \ TAxCCR0
20822 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20823 \ ------------------------------\
20824 \ %0000 0000 0001 0000 \ TAxCCTL0
20825 \ - \ CAP capture/compare mode = compare
20828 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
20829 \ ------------------------------\
20830 \ define LPM mode for ACCEPT \
20831 \ ------------------------------\
20832 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
20833 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20834 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20835 \ ------------------------------\
20837 \ ------------------------------\
20839 \ ------------------------------\
20840 #1000 20_US \ 1- wait 20 ms
20841 %011 TOP_LCD \ 2- send DB5=DB4=1
20842 #205 20_US \ 3- wait 4,1 ms
20843 %011 TOP_LCD \ 4- send again DB5=DB4=1
20844 #5 20_US \ 5- wait 0,1 ms
20845 %011 TOP_LCD \ 6- send again again DB5=DB4=1
20846 #2 20_US \ wait 40 us = LCD cycle
20847 %010 TOP_LCD \ 7- send DB5=1 DB4=0
20848 #2 20_US \ wait 40 us = LCD cycle
20849 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20850 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20851 LCD_CLEAR \ 10- "LCD_Clear"
20852 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20853 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20854 LCD_CLEAR \ 10- "LCD_Clear"
20855 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20856 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20857 CR ." I love you" \ display message on LCD
20858 ['] CR >BODY IS CR \ CR executes its default value
20859 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
20860 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20863 \ ------------------------------\
20865 \ ------------------------------\
20866 CODE START \ this routine replaces WARM and COLD default values by these of this application.
20867 \ ------------------------------\
20868 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
20869 0= IF \ if not done, customizes MARKER_DOES
20870 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
20871 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
20872 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
20873 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
20874 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
20875 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
20876 MOV #RC5_INT,&IR_VEC \ init interrupt vector
20877 MOV #INI_R2L,PC \ then execute new INI_APP, without return
20881 \ ------------------------------\
20884 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
20886 MARKER {RC5TOLCD} \ restore the state before MARKER definition
20887 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
20888 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
20889 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
20890 \ {RC5TOLCD}+14: make room to save previous IR_VEC
20892 [UNDEFINED] CONSTANT [IF]
20893 \ https://forth-standard.org/standard/core/CONSTANT
20894 \ CONSTANT <name> n -- define a Forth CONSTANT
20898 MOV TOS,-2(W) \ PFA = n
20905 [UNDEFINED] STATE [IF]
20906 \ https://forth-standard.org/standard/core/STATE
20907 \ STATE -- a-addr holds compiler state
20908 STATEADR CONSTANT STATE
20912 \ https://forth-standard.org/standard/core/Equal
20913 \ = x1 x2 -- flag test x1=x2
20920 XOR #-1,TOS \ 1 flag Z = 1
20925 [UNDEFINED] IF [IF] \ define IF and THEN
20926 \ https://forth-standard.org/standard/core/IF
20927 \ IF -- IFadr initialize conditional forward branch
20928 CODE IF \ immediate
20931 MOV &DP,TOS \ -- HERE
20932 ADD #4,&DP \ compile one word, reserve one word
20933 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
20934 ADD #2,TOS \ -- HERE+2=IFadr
20938 \ https://forth-standard.org/standard/core/THEN
20939 \ THEN IFadr -- resolve forward branch
20940 CODE THEN \ immediate
20941 MOV &DP,0(TOS) \ -- IFadr
20947 [UNDEFINED] ELSE [IF]
20948 \ https://forth-standard.org/standard/core/ELSE
20949 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
20950 CODE ELSE \ immediate
20951 ADD #4,&DP \ make room to compile two words
20952 MOV &DP,W \ W=HERE+4
20954 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
20956 MOV W,TOS \ -- ELSEadr
20961 [UNDEFINED] IS [IF] \ define DEFER! and IS
20963 \ https://forth-standard.org/standard/core/DEFERStore
20964 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
20965 CODE DEFER! \ xt2 xt1 --
20966 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
20971 \ https://forth-standard.org/standard/core/IS
20974 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
20975 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
20976 \ or in a definition : ... ['] U. IS DISPLAY ...
20977 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
20979 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
20983 IF POSTPONE ['] POSTPONE DEFER!
20989 [UNDEFINED] >BODY [IF]
20990 \ https://forth-standard.org/standard/core/toBODY
20991 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
20998 \ CODE 20uS \ n -- 8MHz version
20999 \ BEGIN \ 4 + 16 ~ loop
21000 \ MOV #39,rDOCON \ 39
21007 \ MOV #XDOCON,rDOCON \ 2
21012 CODE 20_US \ n -- n * 20 us
21013 BEGIN \ here we presume that LCD_TIM_IFG = 1...
21015 BIT #1,&LCD_TIM_CTL \ 3
21016 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
21017 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
21019 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
21024 CODE TOP_LCD \ LCD Sample
21025 \ \ if write : %xxxx_WWWW --
21026 \ \ if read : -- %0000_RRRR
21027 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21028 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21029 0= IF \ write LCD bits pattern
21030 AND.B #LCD_DB,TOS \
21031 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21032 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21035 THEN \ read LCD bits pattern
21038 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21039 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21040 AND.B #LCD_DB,TOS \
21044 CODE LCD_WRC \ char -- Write Char
21045 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21047 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
21048 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
21049 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21050 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21051 COLON \ high level word starts here
21052 TOP_LCD 2 20_US \ write high nibble first
21056 CODE LCD_WRF \ func -- Write Fonction
21057 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21061 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
21062 : LCD_HOME $02 LCD_WRF 100 20_us ;
21064 \ [UNDEFINED] OR [IF]
21066 \ \ https://forth-standard.org/standard/core/OR
21067 \ \ C OR x1 x2 -- x3 logical OR
21075 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
21076 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
21077 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
21078 \ : LCD_FN_SET $20 OR LCD_WrF ;
21079 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
21080 \ : LCD_GOTO $80 OR LCD_WrF ;
21083 \ CODE LCD_RDS \ -- status Read Status
21084 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21085 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21086 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21087 \ COLON \ starts a FORTH word
21088 \ TOP_LCD 2 20_us \ -- %0000_HHHH
21089 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
21090 \ HI2LO \ switch from FORTH to assembler
21091 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
21092 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
21093 \ MOV @RSP+,IP \ restore IP saved by COLON
21097 \ CODE LCD_RDC \ -- char Read Char
21098 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21103 \ ******************************\
21104 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21105 \ ******************************\
21106 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
21107 BIT.B #SW2,&SW2_IN \ test switch S2
21108 0= IF \ case of switch S2 pressed
21109 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21111 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
21114 BIT.B #SW1,&SW1_IN \ test switch S1 input
21115 0= IF \ case of Switch S1 pressed
21116 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21118 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21125 \ ******************************\
21126 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
21127 \ ******************************\
21128 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21129 \ ******************************\
21130 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21131 \ \ SMclock = 8|16|24 MHz
21132 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
21133 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
21134 \ \ SR(9)=new Toggle bit memory (ADD on)
21135 \ ******************************\
21136 \ RC5_FirstStartBitHalfCycle: \
21137 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
21138 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
21139 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
21141 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
21142 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
21144 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
21145 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
21147 MOV #1778,X \ RC5_Period * 1us
21148 MOV #14,W \ count of loop
21150 \ ******************************\
21151 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
21152 \ ******************************\ |
21153 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21154 \ RC5_Compute_3/4_Period: \ |
21155 RRUM #1,X \ X=1/2 cycle |
21158 ADD X,Y \ Y=3/4 cycle
21159 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
21161 \ ******************************\
21162 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21163 \ ******************************\
21164 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21165 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
21166 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21167 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21168 SUB #1,W \ decrement count loop
21169 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
21170 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21171 0<> WHILE \ ----> out of loop ----+
21172 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21174 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
21175 CMP Y,X \ 1 | cycle time out of bound ?
21176 U>= IF \ 2 ^ | yes:
21177 BIC #$30,&RC5_TIM_CTL \ | | stop timer
21178 GOTO FW1 \ | | quit on truncated RC5 message
21180 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
21182 REPEAT \ ----> loop back --+ | with X = new RC5_period value
21183 \ ******************************\ |
21184 \ RC5_SampleEndOf: \ <---------------------+
21185 \ ******************************\
21186 BIC #$30,&RC5_TIM_CTL \ stop timer
21187 \ ******************************\
21188 \ RC5_ComputeNewRC5word \
21189 \ ******************************\
21190 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
21191 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
21192 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
21193 \ ******************************\
21194 \ RC5_ComputeC6bit \
21195 \ ******************************\
21196 BIT #BIT14,T \ test /C6 bit in T
21197 0= IF BIS #BIT6,X \ set C6 bit in X
21198 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
21199 \ ******************************\
21200 \ RC5_CommandByteIsDone \ -- BASE RC5_code
21201 \ ******************************\
21202 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
21203 \ ******************************\
21204 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
21205 XOR @RSP,T \ (new XOR old) Toggle bits
21206 BIT #UF10,T \ repeated RC5_command ?
21207 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
21208 XOR #UF10,0(RSP) \ 5 toggle bit memory
21209 \ ******************************\
21210 \ Display IR_RC5 code \
21211 \ ******************************\
21212 SUB #8,PSP \ TOS -- x x x x TOS
21213 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
21214 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
21215 MOV #$10,&BASEADR \ set hexadecimal base
21216 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
21217 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
21218 LO2HI \ switch from assembler to FORTH
21219 LCD_CLEAR \ set LCD cursor at home
21220 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
21221 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
21222 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
21223 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
21224 HI2LO \ -- switch from FORTH to assembler
21225 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
21226 MOV @PSP+,TOS \ -- TOS
21228 MOV @RSP+,SR \ restore SR flags
21229 BIC #%1111_1000,SR \ but force CPU Active Mode
21230 RET \ (instead of RETI)
21234 \ ------------------------------\
21235 HDNCODE STOP_R2L \ define new STOP_APP
21236 \ ------------------------------\
21237 CMP #RET_ADR,&{RC5TOLCD}+8 \
21238 0<> IF \ if previous START executing
21239 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
21240 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
21241 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
21242 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
21243 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
21244 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
21245 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
21246 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
21247 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
21248 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
21253 \ ------------------------------\
21255 \ ------------------------------\
21256 BW1 \ <-- INI_R2L for some events
21258 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
21260 ." RC5toLCD is removed,"
21261 ." type START to restart"
21264 \ ------------------------------\
21266 \ ------------------------------\
21267 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
21268 \ ------------------------------\
21270 \ ------------------------------\
21271 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
21272 \ ------------------------------\
21273 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
21274 \ ------------------------------\
21275 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
21276 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
21278 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
21279 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
21281 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
21282 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
21283 \ CMP #4,TOS \ hardware RST
21284 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
21285 \ CMP #2,TOS \ Power_ON event
21286 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
21288 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
21290 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
21292 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
21293 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
21294 \ ------------------------------\
21295 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
21296 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21297 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21298 \ -- \ID input divider \ 10 = /4
21299 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21300 \ - \TBCLR TimerB Clear
21303 \ -------------------------------\
21304 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21305 \ -- \CM Capture Mode
21310 \ --- \OUTMOD \ 011 = set/reset
21316 \ -------------------------------\
21318 \ -------------------------------\
21320 \ ------------------------------\
21321 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21322 \ ------------------------------\
21323 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21324 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21325 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
21326 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21328 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
21329 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21331 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
21332 \ ------------------------------\
21333 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21334 \ ------------------------------\
21335 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
21336 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21337 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21338 \ ------------------------------\
21339 BIS.B #LCDVo,&LCDVo_DIR \
21340 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
21341 \ ------------------------------\
21342 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21343 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21344 \ ------------------------------\
21345 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21346 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21347 \ ******************************\
21349 \ ******************************\
21350 BIS.B #RC5,&IR_IE \ enable RC5_Int
21351 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21352 \ ******************************\
21353 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21354 \ ******************************\
21355 \ %01 0001 0100 \ TAxCTL
21356 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
21357 \ -- \ ID divided by 1
21358 \ -- \ MC MODE = up to TAxCCRn
21359 \ - \ TACLR clear timer count
21362 \ ------------------------------\
21363 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
21364 \ ------------------------------\
21366 \ --- \ TAIDEX pre divisor
21367 \ ------------------------------\
21368 \ %0000 0000 0000 0101 \ TAxCCR0
21369 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
21370 \ ------------------------------\
21371 \ %0000 0000 0001 0000 \ TAxCCTL0
21372 \ - \ CAP capture/compare mode = compare
21375 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
21376 \ ------------------------------\
21377 \ define LPM mode for ACCEPT \
21378 \ ------------------------------\
21379 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
21380 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21381 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21382 \ ------------------------------\
21384 \ ------------------------------\
21386 \ ------------------------------\
21387 #1000 20_US \ 1- wait 20 ms
21388 %011 TOP_LCD \ 2- send DB5=DB4=1
21389 #205 20_US \ 3- wait 4,1 ms
21390 %011 TOP_LCD \ 4- send again DB5=DB4=1
21391 #5 20_US \ 5- wait 0,1 ms
21392 %011 TOP_LCD \ 6- send again again DB5=DB4=1
21393 #2 20_US \ wait 40 us = LCD cycle
21394 %010 TOP_LCD \ 7- send DB5=1 DB4=0
21395 #2 20_US \ wait 40 us = LCD cycle
21396 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21397 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21398 LCD_CLEAR \ 10- "LCD_Clear"
21399 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21400 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21401 LCD_CLEAR \ 10- "LCD_Clear"
21402 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21403 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21404 CR ." I love you" \ display message on LCD
21405 ['] CR >BODY IS CR \ CR executes its default value
21406 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
21407 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21410 \ ------------------------------\
21412 \ ------------------------------\
21413 CODE START \ this routine replaces WARM and COLD default values by these of this application.
21414 \ ------------------------------\
21415 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
21416 0= IF \ if not done, customizes MARKER_DOES
21417 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
21418 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
21419 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
21420 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
21421 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21422 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
21423 MOV #RC5_INT,&IR_VEC \ init interrupt vector
21424 MOV #INI_R2L,PC \ then execute new INI_APP, without return
21428 \ ------------------------------\
21431 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
21433 MARKER {RC5TOLCD} \ restore the state before MARKER definition
21434 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
21435 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
21436 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
21437 \ {RC5TOLCD}+14: make room to save previous IR_VEC
21439 [UNDEFINED] CONSTANT [IF]
21440 \ https://forth-standard.org/standard/core/CONSTANT
21441 \ CONSTANT <name> n -- define a Forth CONSTANT
21445 MOV TOS,-2(W) \ PFA = n
21452 [UNDEFINED] STATE [IF]
21453 \ https://forth-standard.org/standard/core/STATE
21454 \ STATE -- a-addr holds compiler state
21455 STATEADR CONSTANT STATE
21459 \ https://forth-standard.org/standard/core/Equal
21460 \ = x1 x2 -- flag test x1=x2
21467 XOR #-1,TOS \ 1 flag Z = 1
21472 [UNDEFINED] IF [IF] \ define IF and THEN
21473 \ https://forth-standard.org/standard/core/IF
21474 \ IF -- IFadr initialize conditional forward branch
21475 CODE IF \ immediate
21478 MOV &DP,TOS \ -- HERE
21479 ADD #4,&DP \ compile one word, reserve one word
21480 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
21481 ADD #2,TOS \ -- HERE+2=IFadr
21485 \ https://forth-standard.org/standard/core/THEN
21486 \ THEN IFadr -- resolve forward branch
21487 CODE THEN \ immediate
21488 MOV &DP,0(TOS) \ -- IFadr
21494 [UNDEFINED] ELSE [IF]
21495 \ https://forth-standard.org/standard/core/ELSE
21496 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
21497 CODE ELSE \ immediate
21498 ADD #4,&DP \ make room to compile two words
21499 MOV &DP,W \ W=HERE+4
21501 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
21503 MOV W,TOS \ -- ELSEadr
21508 [UNDEFINED] IS [IF] \ define DEFER! and IS
21510 \ https://forth-standard.org/standard/core/DEFERStore
21511 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
21512 CODE DEFER! \ xt2 xt1 --
21513 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
21518 \ https://forth-standard.org/standard/core/IS
21521 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
21522 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
21523 \ or in a definition : ... ['] U. IS DISPLAY ...
21524 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
21526 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
21530 IF POSTPONE ['] POSTPONE DEFER!
21536 [UNDEFINED] >BODY [IF]
21537 \ https://forth-standard.org/standard/core/toBODY
21538 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
21545 \ CODE 20uS \ n -- 8MHz version
21546 \ BEGIN \ 4 + 16 ~ loop
21547 \ MOV #39,rDOCON \ 39
21554 \ MOV #XDOCON,rDOCON \ 2
21559 CODE 20_US \ n -- n * 20 us
21560 BEGIN \ here we presume that LCD_TIM_IFG = 1...
21562 BIT #1,&LCD_TIM_CTL \ 3
21563 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
21564 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
21566 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
21571 CODE TOP_LCD \ LCD Sample
21572 \ \ if write : %xxxx_WWWW --
21573 \ \ if read : -- %0000_RRRR
21574 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21575 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21576 0= IF \ write LCD bits pattern
21577 AND.B #LCD_DB,TOS \
21578 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21579 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21582 THEN \ read LCD bits pattern
21585 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21586 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21587 AND.B #LCD_DB,TOS \
21591 CODE LCD_WRC \ char -- Write Char
21592 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21594 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
21595 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
21596 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21597 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21598 COLON \ high level word starts here
21599 TOP_LCD 2 20_US \ write high nibble first
21603 CODE LCD_WRF \ func -- Write Fonction
21604 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21608 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
21609 : LCD_HOME $02 LCD_WRF 100 20_us ;
21611 \ [UNDEFINED] OR [IF]
21613 \ \ https://forth-standard.org/standard/core/OR
21614 \ \ C OR x1 x2 -- x3 logical OR
21622 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
21623 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
21624 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
21625 \ : LCD_FN_SET $20 OR LCD_WrF ;
21626 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
21627 \ : LCD_GOTO $80 OR LCD_WrF ;
21630 \ CODE LCD_RDS \ -- status Read Status
21631 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21632 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21633 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21634 \ COLON \ starts a FORTH word
21635 \ TOP_LCD 2 20_us \ -- %0000_HHHH
21636 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
21637 \ HI2LO \ switch from FORTH to assembler
21638 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
21639 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
21640 \ MOV @RSP+,IP \ restore IP saved by COLON
21644 \ CODE LCD_RDC \ -- char Read Char
21645 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21650 \ ******************************\
21651 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21652 \ ******************************\
21653 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
21654 BIT.B #SW2,&SW2_IN \ test switch S2
21655 0= IF \ case of switch S2 pressed
21656 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21658 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
21661 BIT.B #SW1,&SW1_IN \ test switch S1 input
21662 0= IF \ case of Switch S1 pressed
21663 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21665 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21672 \ ******************************\
21673 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
21674 \ ******************************\
21675 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21676 \ ******************************\
21677 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21678 \ \ SMclock = 8|16|24 MHz
21679 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
21680 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
21681 \ \ SR(9)=new Toggle bit memory (ADD on)
21682 \ ******************************\
21683 \ RC5_FirstStartBitHalfCycle: \
21684 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
21685 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
21686 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
21688 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
21689 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
21691 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
21692 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
21694 MOV #1778,X \ RC5_Period * 1us
21695 MOV #14,W \ count of loop
21697 \ ******************************\
21698 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
21699 \ ******************************\ |
21700 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21701 \ RC5_Compute_3/4_Period: \ |
21702 RRUM #1,X \ X=1/2 cycle |
21705 ADD X,Y \ Y=3/4 cycle
21706 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
21708 \ ******************************\
21709 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21710 \ ******************************\
21711 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21712 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
21713 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21714 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21715 SUB #1,W \ decrement count loop
21716 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
21717 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21718 0<> WHILE \ ----> out of loop ----+
21719 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21721 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
21722 CMP Y,X \ 1 | cycle time out of bound ?
21723 U>= IF \ 2 ^ | yes:
21724 BIC #$30,&RC5_TIM_CTL \ | | stop timer
21725 GOTO FW1 \ | | quit on truncated RC5 message
21727 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
21729 REPEAT \ ----> loop back --+ | with X = new RC5_period value
21730 \ ******************************\ |
21731 \ RC5_SampleEndOf: \ <---------------------+
21732 \ ******************************\
21733 BIC #$30,&RC5_TIM_CTL \ stop timer
21734 \ ******************************\
21735 \ RC5_ComputeNewRC5word \
21736 \ ******************************\
21737 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
21738 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
21739 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
21740 \ ******************************\
21741 \ RC5_ComputeC6bit \
21742 \ ******************************\
21743 BIT #BIT14,T \ test /C6 bit in T
21744 0= IF BIS #BIT6,X \ set C6 bit in X
21745 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
21746 \ ******************************\
21747 \ RC5_CommandByteIsDone \ -- BASE RC5_code
21748 \ ******************************\
21749 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
21750 \ ******************************\
21751 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
21752 XOR @RSP,T \ (new XOR old) Toggle bits
21753 BIT #UF10,T \ repeated RC5_command ?
21754 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
21755 XOR #UF10,0(RSP) \ 5 toggle bit memory
21756 \ ******************************\
21757 \ Display IR_RC5 code \
21758 \ ******************************\
21759 SUB #8,PSP \ TOS -- x x x x TOS
21760 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
21761 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
21762 MOV #$10,&BASEADR \ set hexadecimal base
21763 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
21764 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
21765 LO2HI \ switch from assembler to FORTH
21766 LCD_CLEAR \ set LCD cursor at home
21767 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
21768 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
21769 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
21770 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
21771 HI2LO \ -- switch from FORTH to assembler
21772 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
21773 MOV @PSP+,TOS \ -- TOS
21775 MOV @RSP+,SR \ restore SR flags
21776 BIC #%1111_1000,SR \ but force CPU Active Mode
21777 RET \ (instead of RETI)
21781 \ ------------------------------\
21782 HDNCODE STOP_R2L \ define new STOP_APP
21783 \ ------------------------------\
21784 CMP #RET_ADR,&{RC5TOLCD}+8 \
21785 0<> IF \ if previous START executing
21786 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
21787 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
21788 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
21789 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
21790 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
21791 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
21792 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
21793 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
21794 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
21795 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
21800 \ ------------------------------\
21802 \ ------------------------------\
21803 BW1 \ <-- INI_R2L for some events
21805 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
21807 ." RC5toLCD is removed,"
21808 ." type START to restart"
21811 \ ------------------------------\
21813 \ ------------------------------\
21814 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
21815 \ ------------------------------\
21817 \ ------------------------------\
21818 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
21819 \ ------------------------------\
21820 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
21821 \ ------------------------------\
21822 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
21823 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
21825 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
21826 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
21828 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
21829 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
21830 \ CMP #4,TOS \ hardware RST
21831 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
21832 \ CMP #2,TOS \ Power_ON event
21833 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
21835 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
21837 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
21839 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
21840 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
21841 \ ------------------------------\
21842 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
21843 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21844 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21845 \ -- \ID input divider \ 10 = /4
21846 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21847 \ - \TBCLR TimerB Clear
21850 \ -------------------------------\
21851 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21852 \ -- \CM Capture Mode
21857 \ --- \OUTMOD \ 011 = set/reset
21863 \ -------------------------------\
21865 \ -------------------------------\
21867 \ ------------------------------\
21868 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21869 \ ------------------------------\
21870 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21871 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21872 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
21873 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21875 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
21876 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21878 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
21879 \ ------------------------------\
21880 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21881 \ ------------------------------\
21882 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
21883 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21884 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21885 \ ------------------------------\
21886 BIS.B #LCDVo,&LCDVo_DIR \
21887 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
21888 \ ------------------------------\
21889 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21890 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21891 \ ------------------------------\
21892 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21893 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21894 \ ******************************\
21896 \ ******************************\
21897 BIS.B #RC5,&IR_IE \ enable RC5_Int
21898 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21899 \ ******************************\
21900 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21901 \ ******************************\
21902 \ %01 0001 0100 \ TAxCTL
21903 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
21904 \ -- \ ID divided by 1
21905 \ -- \ MC MODE = up to TAxCCRn
21906 \ - \ TACLR clear timer count
21909 \ ------------------------------\
21910 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
21911 \ ------------------------------\
21913 \ --- \ TAIDEX pre divisor
21914 \ ------------------------------\
21915 \ %0000 0000 0000 0101 \ TAxCCR0
21916 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
21917 \ ------------------------------\
21918 \ %0000 0000 0001 0000 \ TAxCCTL0
21919 \ - \ CAP capture/compare mode = compare
21922 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
21923 \ ------------------------------\
21924 \ define LPM mode for ACCEPT \
21925 \ ------------------------------\
21926 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
21927 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21928 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21929 \ ------------------------------\
21931 \ ------------------------------\
21933 \ ------------------------------\
21934 #1000 20_US \ 1- wait 20 ms
21935 %011 TOP_LCD \ 2- send DB5=DB4=1
21936 #205 20_US \ 3- wait 4,1 ms
21937 %011 TOP_LCD \ 4- send again DB5=DB4=1
21938 #5 20_US \ 5- wait 0,1 ms
21939 %011 TOP_LCD \ 6- send again again DB5=DB4=1
21940 #2 20_US \ wait 40 us = LCD cycle
21941 %010 TOP_LCD \ 7- send DB5=1 DB4=0
21942 #2 20_US \ wait 40 us = LCD cycle
21943 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21944 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21945 LCD_CLEAR \ 10- "LCD_Clear"
21946 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21947 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21948 LCD_CLEAR \ 10- "LCD_Clear"
21949 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21950 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21951 CR ." I love you" \ display message on LCD
21952 ['] CR >BODY IS CR \ CR executes its default value
21953 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
21954 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21957 \ ------------------------------\
21959 \ ------------------------------\
21960 CODE START \ this routine replaces WARM and COLD default values by these of this application.
21961 \ ------------------------------\
21962 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
21963 0= IF \ if not done, customizes MARKER_DOES
21964 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
21965 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
21966 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
21967 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
21968 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21969 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
21970 MOV #RC5_INT,&IR_VEC \ init interrupt vector
21971 MOV #INI_R2L,PC \ then execute new INI_APP, without return
21975 \ ------------------------------\
21978 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
21980 MARKER {RC5TOLCD} \ restore the state before MARKER definition
21981 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
21982 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
21983 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
21984 \ {RC5TOLCD}+14: make room to save previous IR_VEC
21986 [UNDEFINED] CONSTANT [IF]
21987 \ https://forth-standard.org/standard/core/CONSTANT
21988 \ CONSTANT <name> n -- define a Forth CONSTANT
21992 MOV TOS,-2(W) \ PFA = n
21999 [UNDEFINED] STATE [IF]
22000 \ https://forth-standard.org/standard/core/STATE
22001 \ STATE -- a-addr holds compiler state
22002 STATEADR CONSTANT STATE
22006 \ https://forth-standard.org/standard/core/Equal
22007 \ = x1 x2 -- flag test x1=x2
22014 XOR #-1,TOS \ 1 flag Z = 1
22019 [UNDEFINED] IF [IF] \ define IF and THEN
22020 \ https://forth-standard.org/standard/core/IF
22021 \ IF -- IFadr initialize conditional forward branch
22022 CODE IF \ immediate
22025 MOV &DP,TOS \ -- HERE
22026 ADD #4,&DP \ compile one word, reserve one word
22027 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
22028 ADD #2,TOS \ -- HERE+2=IFadr
22032 \ https://forth-standard.org/standard/core/THEN
22033 \ THEN IFadr -- resolve forward branch
22034 CODE THEN \ immediate
22035 MOV &DP,0(TOS) \ -- IFadr
22041 [UNDEFINED] ELSE [IF]
22042 \ https://forth-standard.org/standard/core/ELSE
22043 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
22044 CODE ELSE \ immediate
22045 ADD #4,&DP \ make room to compile two words
22046 MOV &DP,W \ W=HERE+4
22048 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
22050 MOV W,TOS \ -- ELSEadr
22055 [UNDEFINED] IS [IF] \ define DEFER! and IS
22057 \ https://forth-standard.org/standard/core/DEFERStore
22058 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
22059 CODE DEFER! \ xt2 xt1 --
22060 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
22065 \ https://forth-standard.org/standard/core/IS
22068 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
22069 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
22070 \ or in a definition : ... ['] U. IS DISPLAY ...
22071 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
22073 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
22077 IF POSTPONE ['] POSTPONE DEFER!
22083 [UNDEFINED] >BODY [IF]
22084 \ https://forth-standard.org/standard/core/toBODY
22085 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
22092 \ CODE 20uS \ n -- 8MHz version
22093 \ BEGIN \ 4 + 16 ~ loop
22094 \ MOV #39,rDOCON \ 39
22101 \ MOV #XDOCON,rDOCON \ 2
22106 CODE 20_US \ n -- n * 20 us
22107 BEGIN \ here we presume that LCD_TIM_IFG = 1...
22109 BIT #1,&LCD_TIM_CTL \ 3
22110 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
22111 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
22113 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
22118 CODE TOP_LCD \ LCD Sample
22119 \ \ if write : %xxxx_WWWW --
22120 \ \ if read : -- %0000_RRRR
22121 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22122 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22123 0= IF \ write LCD bits pattern
22124 AND.B #LCD_DB,TOS \
22125 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22126 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22129 THEN \ read LCD bits pattern
22132 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22133 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22134 AND.B #LCD_DB,TOS \
22138 CODE LCD_WRC \ char -- Write Char
22139 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22141 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
22142 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
22143 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22144 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22145 COLON \ high level word starts here
22146 TOP_LCD 2 20_US \ write high nibble first
22150 CODE LCD_WRF \ func -- Write Fonction
22151 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22155 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
22156 : LCD_HOME $02 LCD_WRF 100 20_us ;
22158 \ [UNDEFINED] OR [IF]
22160 \ \ https://forth-standard.org/standard/core/OR
22161 \ \ C OR x1 x2 -- x3 logical OR
22169 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
22170 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
22171 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
22172 \ : LCD_FN_SET $20 OR LCD_WrF ;
22173 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
22174 \ : LCD_GOTO $80 OR LCD_WrF ;
22177 \ CODE LCD_RDS \ -- status Read Status
22178 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22179 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22180 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22181 \ COLON \ starts a FORTH word
22182 \ TOP_LCD 2 20_us \ -- %0000_HHHH
22183 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
22184 \ HI2LO \ switch from FORTH to assembler
22185 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
22186 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
22187 \ MOV @RSP+,IP \ restore IP saved by COLON
22191 \ CODE LCD_RDC \ -- char Read Char
22192 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22197 \ ******************************\
22198 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22199 \ ******************************\
22200 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
22201 BIT.B #SW2,&SW2_IN \ test switch S2
22202 0= IF \ case of switch S2 pressed
22203 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22205 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
22208 BIT.B #SW1,&SW1_IN \ test switch S1 input
22209 0= IF \ case of Switch S1 pressed
22210 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
22212 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
22219 \ ******************************\
22220 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
22221 \ ******************************\
22222 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22223 \ ******************************\
22224 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22225 \ \ SMclock = 8|16|24 MHz
22226 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22227 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22228 \ \ SR(9)=new Toggle bit memory (ADD on)
22229 \ ******************************\
22230 \ RC5_FirstStartBitHalfCycle: \
22231 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22232 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
22233 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
22235 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
22236 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
22238 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
22239 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
22241 MOV #1778,X \ RC5_Period * 1us
22242 MOV #14,W \ count of loop
22244 \ ******************************\
22245 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
22246 \ ******************************\ |
22247 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22248 \ RC5_Compute_3/4_Period: \ |
22249 RRUM #1,X \ X=1/2 cycle |
22252 ADD X,Y \ Y=3/4 cycle
22253 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
22255 \ ******************************\
22256 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22257 \ ******************************\
22258 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22259 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
22260 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22261 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22262 SUB #1,W \ decrement count loop
22263 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
22264 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22265 0<> WHILE \ ----> out of loop ----+
22266 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22268 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
22269 CMP Y,X \ 1 | cycle time out of bound ?
22270 U>= IF \ 2 ^ | yes:
22271 BIC #$30,&RC5_TIM_CTL \ | | stop timer
22272 GOTO FW1 \ | | quit on truncated RC5 message
22274 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
22276 REPEAT \ ----> loop back --+ | with X = new RC5_period value
22277 \ ******************************\ |
22278 \ RC5_SampleEndOf: \ <---------------------+
22279 \ ******************************\
22280 BIC #$30,&RC5_TIM_CTL \ stop timer
22281 \ ******************************\
22282 \ RC5_ComputeNewRC5word \
22283 \ ******************************\
22284 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
22285 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
22286 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
22287 \ ******************************\
22288 \ RC5_ComputeC6bit \
22289 \ ******************************\
22290 BIT #BIT14,T \ test /C6 bit in T
22291 0= IF BIS #BIT6,X \ set C6 bit in X
22292 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
22293 \ ******************************\
22294 \ RC5_CommandByteIsDone \ -- BASE RC5_code
22295 \ ******************************\
22296 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
22297 \ ******************************\
22298 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
22299 XOR @RSP,T \ (new XOR old) Toggle bits
22300 BIT #UF10,T \ repeated RC5_command ?
22301 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
22302 XOR #UF10,0(RSP) \ 5 toggle bit memory
22303 \ ******************************\
22304 \ Display IR_RC5 code \
22305 \ ******************************\
22306 SUB #8,PSP \ TOS -- x x x x TOS
22307 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
22308 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
22309 MOV #$10,&BASEADR \ set hexadecimal base
22310 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
22311 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
22312 LO2HI \ switch from assembler to FORTH
22313 LCD_CLEAR \ set LCD cursor at home
22314 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
22315 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
22316 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
22317 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
22318 HI2LO \ -- switch from FORTH to assembler
22319 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
22320 MOV @PSP+,TOS \ -- TOS
22322 MOV @RSP+,SR \ restore SR flags
22323 BIC #%1111_1000,SR \ but force CPU Active Mode
22324 RET \ (instead of RETI)
22328 \ ------------------------------\
22329 HDNCODE STOP_R2L \ define new STOP_APP
22330 \ ------------------------------\
22331 CMP #RET_ADR,&{RC5TOLCD}+8 \
22332 0<> IF \ if previous START executing
22333 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
22334 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
22335 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
22336 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
22337 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
22338 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
22339 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
22340 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
22341 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
22342 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
22347 \ ------------------------------\
22349 \ ------------------------------\
22350 BW1 \ <-- INI_R2L for some events
22352 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
22354 ." RC5toLCD is removed,"
22355 ." type START to restart"
22358 \ ------------------------------\
22360 \ ------------------------------\
22361 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
22362 \ ------------------------------\
22364 \ ------------------------------\
22365 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
22366 \ ------------------------------\
22367 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
22368 \ ------------------------------\
22369 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
22370 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
22372 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
22373 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
22375 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
22376 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
22377 \ CMP #4,TOS \ hardware RST
22378 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
22379 \ CMP #2,TOS \ Power_ON event
22380 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22382 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22384 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22386 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22387 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
22388 \ ------------------------------\
22389 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
22390 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22391 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22392 \ -- \ID input divider \ 10 = /4
22393 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22394 \ - \TBCLR TimerB Clear
22397 \ -------------------------------\
22398 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22399 \ -- \CM Capture Mode
22404 \ --- \OUTMOD \ 011 = set/reset
22410 \ -------------------------------\
22412 \ -------------------------------\
22414 \ ------------------------------\
22415 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22416 \ ------------------------------\
22417 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22418 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22419 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
22420 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22422 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
22423 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22425 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
22426 \ ------------------------------\
22427 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22428 \ ------------------------------\
22429 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
22430 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22431 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22432 \ ------------------------------\
22433 BIS.B #LCDVo,&LCDVo_DIR \
22434 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
22435 \ ------------------------------\
22436 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22437 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22438 \ ------------------------------\
22439 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22440 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22441 \ ******************************\
22443 \ ******************************\
22444 BIS.B #RC5,&IR_IE \ enable RC5_Int
22445 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22446 \ ******************************\
22447 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22448 \ ******************************\
22449 \ %01 0001 0100 \ TAxCTL
22450 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
22451 \ -- \ ID divided by 1
22452 \ -- \ MC MODE = up to TAxCCRn
22453 \ - \ TACLR clear timer count
22456 \ ------------------------------\
22457 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
22458 \ ------------------------------\
22460 \ --- \ TAIDEX pre divisor
22461 \ ------------------------------\
22462 \ %0000 0000 0000 0101 \ TAxCCR0
22463 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22464 \ ------------------------------\
22465 \ %0000 0000 0001 0000 \ TAxCCTL0
22466 \ - \ CAP capture/compare mode = compare
22469 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
22470 \ ------------------------------\
22471 \ define LPM mode for ACCEPT \
22472 \ ------------------------------\
22473 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
22474 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22475 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22476 \ ------------------------------\
22478 \ ------------------------------\
22480 \ ------------------------------\
22481 #1000 20_US \ 1- wait 20 ms
22482 %011 TOP_LCD \ 2- send DB5=DB4=1
22483 #205 20_US \ 3- wait 4,1 ms
22484 %011 TOP_LCD \ 4- send again DB5=DB4=1
22485 #5 20_US \ 5- wait 0,1 ms
22486 %011 TOP_LCD \ 6- send again again DB5=DB4=1
22487 #2 20_US \ wait 40 us = LCD cycle
22488 %010 TOP_LCD \ 7- send DB5=1 DB4=0
22489 #2 20_US \ wait 40 us = LCD cycle
22490 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22491 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22492 LCD_CLEAR \ 10- "LCD_Clear"
22493 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22494 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22495 LCD_CLEAR \ 10- "LCD_Clear"
22496 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22497 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22498 CR ." I love you" \ display message on LCD
22499 ['] CR >BODY IS CR \ CR executes its default value
22500 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
22501 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22504 \ ------------------------------\
22506 \ ------------------------------\
22507 CODE START \ this routine replaces WARM and COLD default values by these of this application.
22508 \ ------------------------------\
22509 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
22510 0= IF \ if not done, customizes MARKER_DOES
22511 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
22512 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
22513 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
22514 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
22515 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22516 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
22517 MOV #RC5_INT,&IR_VEC \ init interrupt vector
22518 MOV #INI_R2L,PC \ then execute new INI_APP, without return
22522 \ ------------------------------\
22525 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
22527 MARKER {RC5TOLCD} \ restore the state before MARKER definition
22528 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
22529 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
22530 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
22531 \ {RC5TOLCD}+14: make room to save previous IR_VEC
22533 [UNDEFINED] CONSTANT [IF]
22534 \ https://forth-standard.org/standard/core/CONSTANT
22535 \ CONSTANT <name> n -- define a Forth CONSTANT
22539 MOV TOS,-2(W) \ PFA = n
22546 [UNDEFINED] STATE [IF]
22547 \ https://forth-standard.org/standard/core/STATE
22548 \ STATE -- a-addr holds compiler state
22549 STATEADR CONSTANT STATE
22553 \ https://forth-standard.org/standard/core/Equal
22554 \ = x1 x2 -- flag test x1=x2
22561 XOR #-1,TOS \ 1 flag Z = 1
22566 [UNDEFINED] IF [IF] \ define IF and THEN
22567 \ https://forth-standard.org/standard/core/IF
22568 \ IF -- IFadr initialize conditional forward branch
22569 CODE IF \ immediate
22572 MOV &DP,TOS \ -- HERE
22573 ADD #4,&DP \ compile one word, reserve one word
22574 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
22575 ADD #2,TOS \ -- HERE+2=IFadr
22579 \ https://forth-standard.org/standard/core/THEN
22580 \ THEN IFadr -- resolve forward branch
22581 CODE THEN \ immediate
22582 MOV &DP,0(TOS) \ -- IFadr
22588 [UNDEFINED] ELSE [IF]
22589 \ https://forth-standard.org/standard/core/ELSE
22590 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
22591 CODE ELSE \ immediate
22592 ADD #4,&DP \ make room to compile two words
22593 MOV &DP,W \ W=HERE+4
22595 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
22597 MOV W,TOS \ -- ELSEadr
22602 [UNDEFINED] IS [IF] \ define DEFER! and IS
22604 \ https://forth-standard.org/standard/core/DEFERStore
22605 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
22606 CODE DEFER! \ xt2 xt1 --
22607 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
22612 \ https://forth-standard.org/standard/core/IS
22615 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
22616 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
22617 \ or in a definition : ... ['] U. IS DISPLAY ...
22618 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
22620 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
22624 IF POSTPONE ['] POSTPONE DEFER!
22630 [UNDEFINED] >BODY [IF]
22631 \ https://forth-standard.org/standard/core/toBODY
22632 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
22639 \ CODE 20uS \ n -- 8MHz version
22640 \ BEGIN \ 4 + 16 ~ loop
22641 \ MOV #39,rDOCON \ 39
22648 \ MOV #XDOCON,rDOCON \ 2
22653 CODE 20_US \ n -- n * 20 us
22654 BEGIN \ here we presume that LCD_TIM_IFG = 1...
22656 BIT #1,&LCD_TIM_CTL \ 3
22657 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
22658 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
22660 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
22665 CODE TOP_LCD \ LCD Sample
22666 \ \ if write : %xxxx_WWWW --
22667 \ \ if read : -- %0000_RRRR
22668 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22669 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22670 0= IF \ write LCD bits pattern
22671 AND.B #LCD_DB,TOS \
22672 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22673 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22676 THEN \ read LCD bits pattern
22679 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22680 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22681 AND.B #LCD_DB,TOS \
22685 CODE LCD_WRC \ char -- Write Char
22686 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22688 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
22689 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
22690 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22691 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22692 COLON \ high level word starts here
22693 TOP_LCD 2 20_US \ write high nibble first
22697 CODE LCD_WRF \ func -- Write Fonction
22698 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22702 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
22703 : LCD_HOME $02 LCD_WRF 100 20_us ;
22705 \ [UNDEFINED] OR [IF]
22707 \ \ https://forth-standard.org/standard/core/OR
22708 \ \ C OR x1 x2 -- x3 logical OR
22716 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
22717 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
22718 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
22719 \ : LCD_FN_SET $20 OR LCD_WrF ;
22720 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
22721 \ : LCD_GOTO $80 OR LCD_WrF ;
22724 \ CODE LCD_RDS \ -- status Read Status
22725 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22726 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22727 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22728 \ COLON \ starts a FORTH word
22729 \ TOP_LCD 2 20_us \ -- %0000_HHHH
22730 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
22731 \ HI2LO \ switch from FORTH to assembler
22732 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
22733 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
22734 \ MOV @RSP+,IP \ restore IP saved by COLON
22738 \ CODE LCD_RDC \ -- char Read Char
22739 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22744 \ ******************************\
22745 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22746 \ ******************************\
22747 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
22748 BIT.B #SW2,&SW2_IN \ test switch S2
22749 0= IF \ case of switch S2 pressed
22750 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22752 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
22755 BIT.B #SW1,&SW1_IN \ test switch S1 input
22756 0= IF \ case of Switch S1 pressed
22757 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
22759 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
22766 \ ******************************\
22767 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
22768 \ ******************************\
22769 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22770 \ ******************************\
22771 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22772 \ \ SMclock = 8|16|24 MHz
22773 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22774 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22775 \ \ SR(9)=new Toggle bit memory (ADD on)
22776 \ ******************************\
22777 \ RC5_FirstStartBitHalfCycle: \
22778 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22779 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
22780 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
22782 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
22783 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
22785 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
22786 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
22788 MOV #1778,X \ RC5_Period * 1us
22789 MOV #14,W \ count of loop
22791 \ ******************************\
22792 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
22793 \ ******************************\ |
22794 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22795 \ RC5_Compute_3/4_Period: \ |
22796 RRUM #1,X \ X=1/2 cycle |
22799 ADD X,Y \ Y=3/4 cycle
22800 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
22802 \ ******************************\
22803 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22804 \ ******************************\
22805 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22806 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
22807 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22808 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22809 SUB #1,W \ decrement count loop
22810 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
22811 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22812 0<> WHILE \ ----> out of loop ----+
22813 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22815 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
22816 CMP Y,X \ 1 | cycle time out of bound ?
22817 U>= IF \ 2 ^ | yes:
22818 BIC #$30,&RC5_TIM_CTL \ | | stop timer
22819 GOTO FW1 \ | | quit on truncated RC5 message
22821 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
22823 REPEAT \ ----> loop back --+ | with X = new RC5_period value
22824 \ ******************************\ |
22825 \ RC5_SampleEndOf: \ <---------------------+
22826 \ ******************************\
22827 BIC #$30,&RC5_TIM_CTL \ stop timer
22828 \ ******************************\
22829 \ RC5_ComputeNewRC5word \
22830 \ ******************************\
22831 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
22832 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
22833 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
22834 \ ******************************\
22835 \ RC5_ComputeC6bit \
22836 \ ******************************\
22837 BIT #BIT14,T \ test /C6 bit in T
22838 0= IF BIS #BIT6,X \ set C6 bit in X
22839 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
22840 \ ******************************\
22841 \ RC5_CommandByteIsDone \ -- BASE RC5_code
22842 \ ******************************\
22843 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
22844 \ ******************************\
22845 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
22846 XOR @RSP,T \ (new XOR old) Toggle bits
22847 BIT #UF10,T \ repeated RC5_command ?
22848 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
22849 XOR #UF10,0(RSP) \ 5 toggle bit memory
22850 \ ******************************\
22851 \ Display IR_RC5 code \
22852 \ ******************************\
22853 SUB #8,PSP \ TOS -- x x x x TOS
22854 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
22855 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
22856 MOV #$10,&BASEADR \ set hexadecimal base
22857 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
22858 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
22859 LO2HI \ switch from assembler to FORTH
22860 LCD_CLEAR \ set LCD cursor at home
22861 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
22862 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
22863 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
22864 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
22865 HI2LO \ -- switch from FORTH to assembler
22866 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
22867 MOV @PSP+,TOS \ -- TOS
22869 MOV @RSP+,SR \ restore SR flags
22870 BIC #%1111_1000,SR \ but force CPU Active Mode
22871 RET \ (instead of RETI)
22875 \ ------------------------------\
22876 HDNCODE STOP_R2L \ define new STOP_APP
22877 \ ------------------------------\
22878 CMP #RET_ADR,&{RC5TOLCD}+8 \
22879 0<> IF \ if previous START executing
22880 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
22881 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
22882 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
22883 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
22884 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
22885 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
22886 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
22887 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
22888 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
22889 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
22894 \ ------------------------------\
22896 \ ------------------------------\
22897 BW1 \ <-- INI_R2L for some events
22899 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
22901 ." RC5toLCD is removed,"
22902 ." type START to restart"
22905 \ ------------------------------\
22907 \ ------------------------------\
22908 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
22909 \ ------------------------------\
22911 \ ------------------------------\
22912 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
22913 \ ------------------------------\
22914 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
22915 \ ------------------------------\
22916 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
22917 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
22919 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
22920 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
22922 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
22923 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
22924 \ CMP #4,TOS \ hardware RST
22925 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
22926 \ CMP #2,TOS \ Power_ON event
22927 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22929 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22931 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22933 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22934 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
22935 \ ------------------------------\
22936 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
22937 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22938 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22939 \ -- \ID input divider \ 10 = /4
22940 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22941 \ - \TBCLR TimerB Clear
22944 \ -------------------------------\
22945 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22946 \ -- \CM Capture Mode
22951 \ --- \OUTMOD \ 011 = set/reset
22957 \ -------------------------------\
22959 \ -------------------------------\
22961 \ ------------------------------\
22962 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22963 \ ------------------------------\
22964 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22965 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22966 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
22967 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22969 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
22970 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22972 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
22973 \ ------------------------------\
22974 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22975 \ ------------------------------\
22976 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
22977 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22978 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22979 \ ------------------------------\
22980 BIS.B #LCDVo,&LCDVo_DIR \
22981 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
22982 \ ------------------------------\
22983 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22984 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22985 \ ------------------------------\
22986 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22987 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22988 \ ******************************\
22990 \ ******************************\
22991 BIS.B #RC5,&IR_IE \ enable RC5_Int
22992 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22993 \ ******************************\
22994 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22995 \ ******************************\
22996 \ %01 0001 0100 \ TAxCTL
22997 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
22998 \ -- \ ID divided by 1
22999 \ -- \ MC MODE = up to TAxCCRn
23000 \ - \ TACLR clear timer count
23003 \ ------------------------------\
23004 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
23005 \ ------------------------------\
23007 \ --- \ TAIDEX pre divisor
23008 \ ------------------------------\
23009 \ %0000 0000 0000 0101 \ TAxCCR0
23010 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
23011 \ ------------------------------\
23012 \ %0000 0000 0001 0000 \ TAxCCTL0
23013 \ - \ CAP capture/compare mode = compare
23016 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
23017 \ ------------------------------\
23018 \ define LPM mode for ACCEPT \
23019 \ ------------------------------\
23020 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
23021 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23022 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23023 \ ------------------------------\
23025 \ ------------------------------\
23027 \ ------------------------------\
23028 #1000 20_US \ 1- wait 20 ms
23029 %011 TOP_LCD \ 2- send DB5=DB4=1
23030 #205 20_US \ 3- wait 4,1 ms
23031 %011 TOP_LCD \ 4- send again DB5=DB4=1
23032 #5 20_US \ 5- wait 0,1 ms
23033 %011 TOP_LCD \ 6- send again again DB5=DB4=1
23034 #2 20_US \ wait 40 us = LCD cycle
23035 %010 TOP_LCD \ 7- send DB5=1 DB4=0
23036 #2 20_US \ wait 40 us = LCD cycle
23037 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23038 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23039 LCD_CLEAR \ 10- "LCD_Clear"
23040 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23041 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23042 LCD_CLEAR \ 10- "LCD_Clear"
23043 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23044 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23045 CR ." I love you" \ display message on LCD
23046 ['] CR >BODY IS CR \ CR executes its default value
23047 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
23048 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
23051 \ ------------------------------\
23053 \ ------------------------------\
23054 CODE START \ this routine replaces WARM and COLD default values by these of this application.
23055 \ ------------------------------\
23056 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
23057 0= IF \ if not done, customizes MARKER_DOES
23058 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
23059 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
23060 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
23061 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
23062 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
23063 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
23064 MOV #RC5_INT,&IR_VEC \ init interrupt vector
23065 MOV #INI_R2L,PC \ then execute new INI_APP, without return
23069 \ ------------------------------\
23072 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
23074 MARKER {RC5TOLCD} \ restore the state before MARKER definition
23075 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
23076 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
23077 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
23078 \ {RC5TOLCD}+14: make room to save previous IR_VEC
23080 [UNDEFINED] CONSTANT [IF]
23081 \ https://forth-standard.org/standard/core/CONSTANT
23082 \ CONSTANT <name> n -- define a Forth CONSTANT
23086 MOV TOS,-2(W) \ PFA = n
23093 [UNDEFINED] STATE [IF]
23094 \ https://forth-standard.org/standard/core/STATE
23095 \ STATE -- a-addr holds compiler state
23096 STATEADR CONSTANT STATE
23100 \ https://forth-standard.org/standard/core/Equal
23101 \ = x1 x2 -- flag test x1=x2
23108 XOR #-1,TOS \ 1 flag Z = 1
23113 [UNDEFINED] IF [IF] \ define IF and THEN
23114 \ https://forth-standard.org/standard/core/IF
23115 \ IF -- IFadr initialize conditional forward branch
23116 CODE IF \ immediate
23119 MOV &DP,TOS \ -- HERE
23120 ADD #4,&DP \ compile one word, reserve one word
23121 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
23122 ADD #2,TOS \ -- HERE+2=IFadr
23126 \ https://forth-standard.org/standard/core/THEN
23127 \ THEN IFadr -- resolve forward branch
23128 CODE THEN \ immediate
23129 MOV &DP,0(TOS) \ -- IFadr
23135 [UNDEFINED] ELSE [IF]
23136 \ https://forth-standard.org/standard/core/ELSE
23137 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
23138 CODE ELSE \ immediate
23139 ADD #4,&DP \ make room to compile two words
23140 MOV &DP,W \ W=HERE+4
23142 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
23144 MOV W,TOS \ -- ELSEadr
23149 [UNDEFINED] IS [IF] \ define DEFER! and IS
23151 \ https://forth-standard.org/standard/core/DEFERStore
23152 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
23153 CODE DEFER! \ xt2 xt1 --
23154 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
23159 \ https://forth-standard.org/standard/core/IS
23162 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
23163 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
23164 \ or in a definition : ... ['] U. IS DISPLAY ...
23165 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
23167 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
23171 IF POSTPONE ['] POSTPONE DEFER!
23177 [UNDEFINED] >BODY [IF]
23178 \ https://forth-standard.org/standard/core/toBODY
23179 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
23186 \ CODE 20uS \ n -- 8MHz version
23187 \ BEGIN \ 4 + 16 ~ loop
23188 \ MOV #39,rDOCON \ 39
23195 \ MOV #XDOCON,rDOCON \ 2
23200 CODE 20_US \ n -- n * 20 us
23201 BEGIN \ here we presume that LCD_TIM_IFG = 1...
23203 BIT #1,&LCD_TIM_CTL \ 3
23204 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
23205 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
23207 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
23212 CODE TOP_LCD \ LCD Sample
23213 \ \ if write : %xxxx_WWWW --
23214 \ \ if read : -- %0000_RRRR
23215 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23216 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23217 0= IF \ write LCD bits pattern
23218 AND.B #LCD_DB,TOS \
23219 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23220 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23223 THEN \ read LCD bits pattern
23226 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23227 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23228 AND.B #LCD_DB,TOS \
23232 CODE LCD_WRC \ char -- Write Char
23233 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23235 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
23236 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
23237 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23238 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23239 COLON \ high level word starts here
23240 TOP_LCD 2 20_US \ write high nibble first
23244 CODE LCD_WRF \ func -- Write Fonction
23245 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23249 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
23250 : LCD_HOME $02 LCD_WRF 100 20_us ;
23252 \ [UNDEFINED] OR [IF]
23254 \ \ https://forth-standard.org/standard/core/OR
23255 \ \ C OR x1 x2 -- x3 logical OR
23263 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
23264 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
23265 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
23266 \ : LCD_FN_SET $20 OR LCD_WrF ;
23267 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
23268 \ : LCD_GOTO $80 OR LCD_WrF ;
23271 \ CODE LCD_RDS \ -- status Read Status
23272 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23273 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23274 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23275 \ COLON \ starts a FORTH word
23276 \ TOP_LCD 2 20_us \ -- %0000_HHHH
23277 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
23278 \ HI2LO \ switch from FORTH to assembler
23279 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
23280 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
23281 \ MOV @RSP+,IP \ restore IP saved by COLON
23285 \ CODE LCD_RDC \ -- char Read Char
23286 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23291 \ ******************************\
23292 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23293 \ ******************************\
23294 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
23295 BIT.B #SW2,&SW2_IN \ test switch S2
23296 0= IF \ case of switch S2 pressed
23297 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23299 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
23302 BIT.B #SW1,&SW1_IN \ test switch S1 input
23303 0= IF \ case of Switch S1 pressed
23304 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23306 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23313 \ ******************************\
23314 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
23315 \ ******************************\
23316 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23317 \ ******************************\
23318 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23319 \ \ SMclock = 8|16|24 MHz
23320 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23321 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23322 \ \ SR(9)=new Toggle bit memory (ADD on)
23323 \ ******************************\
23324 \ RC5_FirstStartBitHalfCycle: \
23325 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23326 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23327 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23329 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23330 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23332 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23333 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23335 MOV #1778,X \ RC5_Period * 1us
23336 MOV #14,W \ count of loop
23338 \ ******************************\
23339 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23340 \ ******************************\ |
23341 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23342 \ RC5_Compute_3/4_Period: \ |
23343 RRUM #1,X \ X=1/2 cycle |
23346 ADD X,Y \ Y=3/4 cycle
23347 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23349 \ ******************************\
23350 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23351 \ ******************************\
23352 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23353 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23354 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23355 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23356 SUB #1,W \ decrement count loop
23357 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23358 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23359 0<> WHILE \ ----> out of loop ----+
23360 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23362 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23363 CMP Y,X \ 1 | cycle time out of bound ?
23364 U>= IF \ 2 ^ | yes:
23365 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23366 GOTO FW1 \ | | quit on truncated RC5 message
23368 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23370 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23371 \ ******************************\ |
23372 \ RC5_SampleEndOf: \ <---------------------+
23373 \ ******************************\
23374 BIC #$30,&RC5_TIM_CTL \ stop timer
23375 \ ******************************\
23376 \ RC5_ComputeNewRC5word \
23377 \ ******************************\
23378 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23379 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23380 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23381 \ ******************************\
23382 \ RC5_ComputeC6bit \
23383 \ ******************************\
23384 BIT #BIT14,T \ test /C6 bit in T
23385 0= IF BIS #BIT6,X \ set C6 bit in X
23386 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23387 \ ******************************\
23388 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23389 \ ******************************\
23390 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
23391 \ ******************************\
23392 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23393 XOR @RSP,T \ (new XOR old) Toggle bits
23394 BIT #UF10,T \ repeated RC5_command ?
23395 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
23396 XOR #UF10,0(RSP) \ 5 toggle bit memory
23397 \ ******************************\
23398 \ Display IR_RC5 code \
23399 \ ******************************\
23400 SUB #8,PSP \ TOS -- x x x x TOS
23401 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23402 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23403 MOV #$10,&BASEADR \ set hexadecimal base
23404 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23405 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23406 LO2HI \ switch from assembler to FORTH
23407 LCD_CLEAR \ set LCD cursor at home
23408 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23409 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23410 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23411 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23412 HI2LO \ -- switch from FORTH to assembler
23413 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23414 MOV @PSP+,TOS \ -- TOS
23416 MOV @RSP+,SR \ restore SR flags
23417 BIC #%1111_1000,SR \ but force CPU Active Mode
23418 RET \ (instead of RETI)
23422 \ ------------------------------\
23423 HDNCODE STOP_R2L \ define new STOP_APP
23424 \ ------------------------------\
23425 CMP #RET_ADR,&{RC5TOLCD}+8 \
23426 0<> IF \ if previous START executing
23427 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
23428 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
23429 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
23430 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
23431 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
23432 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
23433 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
23434 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
23435 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
23436 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
23441 \ ------------------------------\
23443 \ ------------------------------\
23444 BW1 \ <-- INI_R2L for some events
23446 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23448 ." RC5toLCD is removed,"
23449 ." type START to restart"
23452 \ ------------------------------\
23454 \ ------------------------------\
23455 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
23456 \ ------------------------------\
23458 \ ------------------------------\
23459 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
23460 \ ------------------------------\
23461 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
23462 \ ------------------------------\
23463 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
23464 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
23466 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
23467 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
23469 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
23470 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
23471 \ CMP #4,TOS \ hardware RST
23472 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
23473 \ CMP #2,TOS \ Power_ON event
23474 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
23476 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
23478 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
23480 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
23481 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
23482 \ ------------------------------\
23483 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
23484 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23485 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23486 \ -- \ID input divider \ 10 = /4
23487 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
23488 \ - \TBCLR TimerB Clear
23491 \ -------------------------------\
23492 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23493 \ -- \CM Capture Mode
23498 \ --- \OUTMOD \ 011 = set/reset
23504 \ -------------------------------\
23506 \ -------------------------------\
23508 \ ------------------------------\
23509 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
23510 \ ------------------------------\
23511 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
23512 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
23513 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
23514 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
23516 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
23517 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
23519 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
23520 \ ------------------------------\
23521 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
23522 \ ------------------------------\
23523 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
23524 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
23525 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23526 \ ------------------------------\
23527 BIS.B #LCDVo,&LCDVo_DIR \
23528 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
23529 \ ------------------------------\
23530 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23531 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23532 \ ------------------------------\
23533 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23534 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23535 \ ******************************\
23537 \ ******************************\
23538 BIS.B #RC5,&IR_IE \ enable RC5_Int
23539 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23540 \ ******************************\
23541 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
23542 \ ******************************\
23543 \ %01 0001 0100 \ TAxCTL
23544 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
23545 \ -- \ ID divided by 1
23546 \ -- \ MC MODE = up to TAxCCRn
23547 \ - \ TACLR clear timer count
23550 \ ------------------------------\
23551 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
23552 \ ------------------------------\
23554 \ --- \ TAIDEX pre divisor
23555 \ ------------------------------\
23556 \ %0000 0000 0000 0101 \ TAxCCR0
23557 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
23558 \ ------------------------------\
23559 \ %0000 0000 0001 0000 \ TAxCCTL0
23560 \ - \ CAP capture/compare mode = compare
23563 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
23564 \ ------------------------------\
23565 \ define LPM mode for ACCEPT \
23566 \ ------------------------------\
23567 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
23568 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23569 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23570 \ ------------------------------\
23572 \ ------------------------------\
23574 \ ------------------------------\
23575 #1000 20_US \ 1- wait 20 ms
23576 %011 TOP_LCD \ 2- send DB5=DB4=1
23577 #205 20_US \ 3- wait 4,1 ms
23578 %011 TOP_LCD \ 4- send again DB5=DB4=1
23579 #5 20_US \ 5- wait 0,1 ms
23580 %011 TOP_LCD \ 6- send again again DB5=DB4=1
23581 #2 20_US \ wait 40 us = LCD cycle
23582 %010 TOP_LCD \ 7- send DB5=1 DB4=0
23583 #2 20_US \ wait 40 us = LCD cycle
23584 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23585 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23586 LCD_CLEAR \ 10- "LCD_Clear"
23587 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23588 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23589 LCD_CLEAR \ 10- "LCD_Clear"
23590 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23591 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23592 CR ." I love you" \ display message on LCD
23593 ['] CR >BODY IS CR \ CR executes its default value
23594 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
23595 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
23598 \ ------------------------------\
23600 \ ------------------------------\
23601 CODE START \ this routine replaces WARM and COLD default values by these of this application.
23602 \ ------------------------------\
23603 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
23604 0= IF \ if not done, customizes MARKER_DOES
23605 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
23606 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
23607 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
23608 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
23609 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
23610 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
23611 MOV #RC5_INT,&IR_VEC \ init interrupt vector
23612 MOV #INI_R2L,PC \ then execute new INI_APP, without return
23616 \ ------------------------------\
23619 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
23621 MARKER {RC5TOLCD} \ restore the state before MARKER definition
23622 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
23623 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
23624 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
23625 \ {RC5TOLCD}+14: make room to save previous IR_VEC
23627 [UNDEFINED] CONSTANT [IF]
23628 \ https://forth-standard.org/standard/core/CONSTANT
23629 \ CONSTANT <name> n -- define a Forth CONSTANT
23633 MOV TOS,-2(W) \ PFA = n
23640 [UNDEFINED] STATE [IF]
23641 \ https://forth-standard.org/standard/core/STATE
23642 \ STATE -- a-addr holds compiler state
23643 STATEADR CONSTANT STATE
23647 \ https://forth-standard.org/standard/core/Equal
23648 \ = x1 x2 -- flag test x1=x2
23655 XOR #-1,TOS \ 1 flag Z = 1
23660 [UNDEFINED] IF [IF] \ define IF and THEN
23661 \ https://forth-standard.org/standard/core/IF
23662 \ IF -- IFadr initialize conditional forward branch
23663 CODE IF \ immediate
23666 MOV &DP,TOS \ -- HERE
23667 ADD #4,&DP \ compile one word, reserve one word
23668 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
23669 ADD #2,TOS \ -- HERE+2=IFadr
23673 \ https://forth-standard.org/standard/core/THEN
23674 \ THEN IFadr -- resolve forward branch
23675 CODE THEN \ immediate
23676 MOV &DP,0(TOS) \ -- IFadr
23682 [UNDEFINED] ELSE [IF]
23683 \ https://forth-standard.org/standard/core/ELSE
23684 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
23685 CODE ELSE \ immediate
23686 ADD #4,&DP \ make room to compile two words
23687 MOV &DP,W \ W=HERE+4
23689 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
23691 MOV W,TOS \ -- ELSEadr
23696 [UNDEFINED] IS [IF] \ define DEFER! and IS
23698 \ https://forth-standard.org/standard/core/DEFERStore
23699 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
23700 CODE DEFER! \ xt2 xt1 --
23701 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
23706 \ https://forth-standard.org/standard/core/IS
23709 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
23710 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
23711 \ or in a definition : ... ['] U. IS DISPLAY ...
23712 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
23714 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
23718 IF POSTPONE ['] POSTPONE DEFER!
23724 [UNDEFINED] >BODY [IF]
23725 \ https://forth-standard.org/standard/core/toBODY
23726 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
23733 \ CODE 20uS \ n -- 8MHz version
23734 \ BEGIN \ 4 + 16 ~ loop
23735 \ MOV #39,rDOCON \ 39
23742 \ MOV #XDOCON,rDOCON \ 2
23747 CODE 20_US \ n -- n * 20 us
23748 BEGIN \ here we presume that LCD_TIM_IFG = 1...
23750 BIT #1,&LCD_TIM_CTL \ 3
23751 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
23752 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
23754 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
23759 CODE TOP_LCD \ LCD Sample
23760 \ \ if write : %xxxx_WWWW --
23761 \ \ if read : -- %0000_RRRR
23762 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23763 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23764 0= IF \ write LCD bits pattern
23765 AND.B #LCD_DB,TOS \
23766 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23767 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23770 THEN \ read LCD bits pattern
23773 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23774 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23775 AND.B #LCD_DB,TOS \
23779 CODE LCD_WRC \ char -- Write Char
23780 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23782 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
23783 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
23784 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23785 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23786 COLON \ high level word starts here
23787 TOP_LCD 2 20_US \ write high nibble first
23791 CODE LCD_WRF \ func -- Write Fonction
23792 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23796 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
23797 : LCD_HOME $02 LCD_WRF 100 20_us ;
23799 \ [UNDEFINED] OR [IF]
23801 \ \ https://forth-standard.org/standard/core/OR
23802 \ \ C OR x1 x2 -- x3 logical OR
23810 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
23811 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
23812 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
23813 \ : LCD_FN_SET $20 OR LCD_WrF ;
23814 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
23815 \ : LCD_GOTO $80 OR LCD_WrF ;
23818 \ CODE LCD_RDS \ -- status Read Status
23819 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23820 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23821 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23822 \ COLON \ starts a FORTH word
23823 \ TOP_LCD 2 20_us \ -- %0000_HHHH
23824 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
23825 \ HI2LO \ switch from FORTH to assembler
23826 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
23827 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
23828 \ MOV @RSP+,IP \ restore IP saved by COLON
23832 \ CODE LCD_RDC \ -- char Read Char
23833 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23838 \ ******************************\
23839 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23840 \ ******************************\
23841 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
23842 BIT.B #SW2,&SW2_IN \ test switch S2
23843 0= IF \ case of switch S2 pressed
23844 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23846 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
23849 BIT.B #SW1,&SW1_IN \ test switch S1 input
23850 0= IF \ case of Switch S1 pressed
23851 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23853 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23860 \ ******************************\
23861 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
23862 \ ******************************\
23863 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23864 \ ******************************\
23865 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23866 \ \ SMclock = 8|16|24 MHz
23867 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23868 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23869 \ \ SR(9)=new Toggle bit memory (ADD on)
23870 \ ******************************\
23871 \ RC5_FirstStartBitHalfCycle: \
23872 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23873 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23874 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23876 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23877 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23879 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23880 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23882 MOV #1778,X \ RC5_Period * 1us
23883 MOV #14,W \ count of loop
23885 \ ******************************\
23886 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23887 \ ******************************\ |
23888 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23889 \ RC5_Compute_3/4_Period: \ |
23890 RRUM #1,X \ X=1/2 cycle |
23893 ADD X,Y \ Y=3/4 cycle
23894 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23896 \ ******************************\
23897 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23898 \ ******************************\
23899 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23900 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23901 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23902 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23903 SUB #1,W \ decrement count loop
23904 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23905 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23906 0<> WHILE \ ----> out of loop ----+
23907 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23909 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23910 CMP Y,X \ 1 | cycle time out of bound ?
23911 U>= IF \ 2 ^ | yes:
23912 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23913 GOTO FW1 \ | | quit on truncated RC5 message
23915 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23917 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23918 \ ******************************\ |
23919 \ RC5_SampleEndOf: \ <---------------------+
23920 \ ******************************\
23921 BIC #$30,&RC5_TIM_CTL \ stop timer
23922 \ ******************************\
23923 \ RC5_ComputeNewRC5word \
23924 \ ******************************\
23925 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23926 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23927 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23928 \ ******************************\
23929 \ RC5_ComputeC6bit \
23930 \ ******************************\
23931 BIT #BIT14,T \ test /C6 bit in T
23932 0= IF BIS #BIT6,X \ set C6 bit in X
23933 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23934 \ ******************************\
23935 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23936 \ ******************************\
23937 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
23938 \ ******************************\
23939 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23940 XOR @RSP,T \ (new XOR old) Toggle bits
23941 BIT #UF10,T \ repeated RC5_command ?
23942 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
23943 XOR #UF10,0(RSP) \ 5 toggle bit memory
23944 \ ******************************\
23945 \ Display IR_RC5 code \
23946 \ ******************************\
23947 SUB #8,PSP \ TOS -- x x x x TOS
23948 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23949 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23950 MOV #$10,&BASEADR \ set hexadecimal base
23951 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23952 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23953 LO2HI \ switch from assembler to FORTH
23954 LCD_CLEAR \ set LCD cursor at home
23955 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23956 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23957 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23958 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23959 HI2LO \ -- switch from FORTH to assembler
23960 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23961 MOV @PSP+,TOS \ -- TOS
23963 MOV @RSP+,SR \ restore SR flags
23964 BIC #%1111_1000,SR \ but force CPU Active Mode
23965 RET \ (instead of RETI)
23969 \ ------------------------------\
23970 HDNCODE STOP_R2L \ define new STOP_APP
23971 \ ------------------------------\
23972 CMP #RET_ADR,&{RC5TOLCD}+8 \
23973 0<> IF \ if previous START executing
23974 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
23975 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
23976 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
23977 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
23978 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
23979 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
23980 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
23981 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
23982 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
23983 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
23988 \ ------------------------------\
23990 \ ------------------------------\
23991 BW1 \ <-- INI_R2L for some events
23993 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23995 ." RC5toLCD is removed,"
23996 ." type START to restart"
23999 \ ------------------------------\
24001 \ ------------------------------\
24002 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
24003 \ ------------------------------\
24005 \ ------------------------------\
24006 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
24007 \ ------------------------------\
24008 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
24009 \ ------------------------------\
24010 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
24011 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
24013 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
24014 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
24016 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
24017 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
24018 \ CMP #4,TOS \ hardware RST
24019 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
24020 \ CMP #2,TOS \ Power_ON event
24021 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24023 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24025 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24027 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24028 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
24029 \ ------------------------------\
24030 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
24031 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24032 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24033 \ -- \ID input divider \ 10 = /4
24034 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24035 \ - \TBCLR TimerB Clear
24038 \ -------------------------------\
24039 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24040 \ -- \CM Capture Mode
24045 \ --- \OUTMOD \ 011 = set/reset
24051 \ -------------------------------\
24053 \ -------------------------------\
24055 \ ------------------------------\
24056 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24057 \ ------------------------------\
24058 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24059 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24060 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
24061 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24063 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
24064 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24066 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24067 \ ------------------------------\
24068 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24069 \ ------------------------------\
24070 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24071 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24072 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24073 \ ------------------------------\
24074 BIS.B #LCDVo,&LCDVo_DIR \
24075 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24076 \ ------------------------------\
24077 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24078 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24079 \ ------------------------------\
24080 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24081 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24082 \ ******************************\
24084 \ ******************************\
24085 BIS.B #RC5,&IR_IE \ enable RC5_Int
24086 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24087 \ ******************************\
24088 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24089 \ ******************************\
24090 \ %01 0001 0100 \ TAxCTL
24091 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24092 \ -- \ ID divided by 1
24093 \ -- \ MC MODE = up to TAxCCRn
24094 \ - \ TACLR clear timer count
24097 \ ------------------------------\
24098 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24099 \ ------------------------------\
24101 \ --- \ TAIDEX pre divisor
24102 \ ------------------------------\
24103 \ %0000 0000 0000 0101 \ TAxCCR0
24104 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24105 \ ------------------------------\
24106 \ %0000 0000 0001 0000 \ TAxCCTL0
24107 \ - \ CAP capture/compare mode = compare
24110 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24111 \ ------------------------------\
24112 \ define LPM mode for ACCEPT \
24113 \ ------------------------------\
24114 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
24115 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24116 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24117 \ ------------------------------\
24119 \ ------------------------------\
24121 \ ------------------------------\
24122 #1000 20_US \ 1- wait 20 ms
24123 %011 TOP_LCD \ 2- send DB5=DB4=1
24124 #205 20_US \ 3- wait 4,1 ms
24125 %011 TOP_LCD \ 4- send again DB5=DB4=1
24126 #5 20_US \ 5- wait 0,1 ms
24127 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24128 #2 20_US \ wait 40 us = LCD cycle
24129 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24130 #2 20_US \ wait 40 us = LCD cycle
24131 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24132 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24133 LCD_CLEAR \ 10- "LCD_Clear"
24134 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24135 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24136 LCD_CLEAR \ 10- "LCD_Clear"
24137 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24138 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24139 CR ." I love you" \ display message on LCD
24140 ['] CR >BODY IS CR \ CR executes its default value
24141 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24142 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24145 \ ------------------------------\
24147 \ ------------------------------\
24148 CODE START \ this routine replaces WARM and COLD default values by these of this application.
24149 \ ------------------------------\
24150 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
24151 0= IF \ if not done, customizes MARKER_DOES
24152 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
24153 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
24154 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
24155 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
24156 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24157 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
24158 MOV #RC5_INT,&IR_VEC \ init interrupt vector
24159 MOV #INI_R2L,PC \ then execute new INI_APP, without return
24163 \ ------------------------------\
24166 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24168 MARKER {RC5TOLCD} \ restore the state before MARKER definition
24169 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
24170 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
24171 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
24172 \ {RC5TOLCD}+14: make room to save previous IR_VEC
24174 [UNDEFINED] CONSTANT [IF]
24175 \ https://forth-standard.org/standard/core/CONSTANT
24176 \ CONSTANT <name> n -- define a Forth CONSTANT
24180 MOV TOS,-2(W) \ PFA = n
24187 [UNDEFINED] STATE [IF]
24188 \ https://forth-standard.org/standard/core/STATE
24189 \ STATE -- a-addr holds compiler state
24190 STATEADR CONSTANT STATE
24194 \ https://forth-standard.org/standard/core/Equal
24195 \ = x1 x2 -- flag test x1=x2
24202 XOR #-1,TOS \ 1 flag Z = 1
24207 [UNDEFINED] IF [IF] \ define IF and THEN
24208 \ https://forth-standard.org/standard/core/IF
24209 \ IF -- IFadr initialize conditional forward branch
24210 CODE IF \ immediate
24213 MOV &DP,TOS \ -- HERE
24214 ADD #4,&DP \ compile one word, reserve one word
24215 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
24216 ADD #2,TOS \ -- HERE+2=IFadr
24220 \ https://forth-standard.org/standard/core/THEN
24221 \ THEN IFadr -- resolve forward branch
24222 CODE THEN \ immediate
24223 MOV &DP,0(TOS) \ -- IFadr
24229 [UNDEFINED] ELSE [IF]
24230 \ https://forth-standard.org/standard/core/ELSE
24231 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
24232 CODE ELSE \ immediate
24233 ADD #4,&DP \ make room to compile two words
24234 MOV &DP,W \ W=HERE+4
24236 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
24238 MOV W,TOS \ -- ELSEadr
24243 [UNDEFINED] IS [IF] \ define DEFER! and IS
24245 \ https://forth-standard.org/standard/core/DEFERStore
24246 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
24247 CODE DEFER! \ xt2 xt1 --
24248 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
24253 \ https://forth-standard.org/standard/core/IS
24256 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
24257 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
24258 \ or in a definition : ... ['] U. IS DISPLAY ...
24259 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
24261 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
24265 IF POSTPONE ['] POSTPONE DEFER!
24271 [UNDEFINED] >BODY [IF]
24272 \ https://forth-standard.org/standard/core/toBODY
24273 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
24280 \ CODE 20uS \ n -- 8MHz version
24281 \ BEGIN \ 4 + 16 ~ loop
24282 \ MOV #39,rDOCON \ 39
24289 \ MOV #XDOCON,rDOCON \ 2
24294 CODE 20_US \ n -- n * 20 us
24295 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24297 BIT #1,&LCD_TIM_CTL \ 3
24298 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24299 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24301 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24306 CODE TOP_LCD \ LCD Sample
24307 \ \ if write : %xxxx_WWWW --
24308 \ \ if read : -- %0000_RRRR
24309 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24310 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24311 0= IF \ write LCD bits pattern
24312 AND.B #LCD_DB,TOS \
24313 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24314 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24317 THEN \ read LCD bits pattern
24320 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24321 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24322 AND.B #LCD_DB,TOS \
24326 CODE LCD_WRC \ char -- Write Char
24327 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24329 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
24330 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
24331 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24332 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24333 COLON \ high level word starts here
24334 TOP_LCD 2 20_US \ write high nibble first
24338 CODE LCD_WRF \ func -- Write Fonction
24339 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24343 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
24344 : LCD_HOME $02 LCD_WRF 100 20_us ;
24346 \ [UNDEFINED] OR [IF]
24348 \ \ https://forth-standard.org/standard/core/OR
24349 \ \ C OR x1 x2 -- x3 logical OR
24357 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
24358 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
24359 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
24360 \ : LCD_FN_SET $20 OR LCD_WrF ;
24361 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
24362 \ : LCD_GOTO $80 OR LCD_WrF ;
24365 \ CODE LCD_RDS \ -- status Read Status
24366 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24367 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24368 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24369 \ COLON \ starts a FORTH word
24370 \ TOP_LCD 2 20_us \ -- %0000_HHHH
24371 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
24372 \ HI2LO \ switch from FORTH to assembler
24373 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
24374 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
24375 \ MOV @RSP+,IP \ restore IP saved by COLON
24379 \ CODE LCD_RDC \ -- char Read Char
24380 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24385 \ ******************************\
24386 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24387 \ ******************************\
24388 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
24389 BIT.B #SW2,&SW2_IN \ test switch S2
24390 0= IF \ case of switch S2 pressed
24391 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
24393 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
24396 BIT.B #SW1,&SW1_IN \ test switch S1 input
24397 0= IF \ case of Switch S1 pressed
24398 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
24400 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
24407 \ ******************************\
24408 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
24409 \ ******************************\
24410 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24411 \ ******************************\
24412 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24413 \ \ SMclock = 8|16|24 MHz
24414 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
24415 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
24416 \ \ SR(9)=new Toggle bit memory (ADD on)
24417 \ ******************************\
24418 \ RC5_FirstStartBitHalfCycle: \
24419 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
24420 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
24421 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
24423 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
24424 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
24426 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
24427 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
24429 MOV #1778,X \ RC5_Period * 1us
24430 MOV #14,W \ count of loop
24432 \ ******************************\
24433 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
24434 \ ******************************\ |
24435 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
24436 \ RC5_Compute_3/4_Period: \ |
24437 RRUM #1,X \ X=1/2 cycle |
24440 ADD X,Y \ Y=3/4 cycle
24441 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
24443 \ ******************************\
24444 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
24445 \ ******************************\
24446 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24447 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
24448 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24449 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24450 SUB #1,W \ decrement count loop
24451 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
24452 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24453 0<> WHILE \ ----> out of loop ----+
24454 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
24456 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
24457 CMP Y,X \ 1 | cycle time out of bound ?
24458 U>= IF \ 2 ^ | yes:
24459 BIC #$30,&RC5_TIM_CTL \ | | stop timer
24460 GOTO FW1 \ | | quit on truncated RC5 message
24462 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
24464 REPEAT \ ----> loop back --+ | with X = new RC5_period value
24465 \ ******************************\ |
24466 \ RC5_SampleEndOf: \ <---------------------+
24467 \ ******************************\
24468 BIC #$30,&RC5_TIM_CTL \ stop timer
24469 \ ******************************\
24470 \ RC5_ComputeNewRC5word \
24471 \ ******************************\
24472 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
24473 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
24474 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
24475 \ ******************************\
24476 \ RC5_ComputeC6bit \
24477 \ ******************************\
24478 BIT #BIT14,T \ test /C6 bit in T
24479 0= IF BIS #BIT6,X \ set C6 bit in X
24480 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
24481 \ ******************************\
24482 \ RC5_CommandByteIsDone \ -- BASE RC5_code
24483 \ ******************************\
24484 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
24485 \ ******************************\
24486 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
24487 XOR @RSP,T \ (new XOR old) Toggle bits
24488 BIT #UF10,T \ repeated RC5_command ?
24489 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
24490 XOR #UF10,0(RSP) \ 5 toggle bit memory
24491 \ ******************************\
24492 \ Display IR_RC5 code \
24493 \ ******************************\
24494 SUB #8,PSP \ TOS -- x x x x TOS
24495 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
24496 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
24497 MOV #$10,&BASEADR \ set hexadecimal base
24498 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
24499 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
24500 LO2HI \ switch from assembler to FORTH
24501 LCD_CLEAR \ set LCD cursor at home
24502 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
24503 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
24504 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
24505 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
24506 HI2LO \ -- switch from FORTH to assembler
24507 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
24508 MOV @PSP+,TOS \ -- TOS
24510 MOV @RSP+,SR \ restore SR flags
24511 BIC #%1111_1000,SR \ but force CPU Active Mode
24512 RET \ (instead of RETI)
24516 \ ------------------------------\
24517 HDNCODE STOP_R2L \ define new STOP_APP
24518 \ ------------------------------\
24519 CMP #RET_ADR,&{RC5TOLCD}+8 \
24520 0<> IF \ if previous START executing
24521 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
24522 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
24523 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
24524 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
24525 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
24526 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
24527 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
24528 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
24529 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
24530 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
24535 \ ------------------------------\
24537 \ ------------------------------\
24538 BW1 \ <-- INI_R2L for some events
24540 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
24542 ." RC5toLCD is removed,"
24543 ." type START to restart"
24546 \ ------------------------------\
24548 \ ------------------------------\
24549 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
24550 \ ------------------------------\
24552 \ ------------------------------\
24553 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
24554 \ ------------------------------\
24555 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
24556 \ ------------------------------\
24557 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
24558 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
24560 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
24561 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
24563 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
24564 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
24565 \ CMP #4,TOS \ hardware RST
24566 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
24567 \ CMP #2,TOS \ Power_ON event
24568 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24570 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24572 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24574 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24575 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
24576 \ ------------------------------\
24577 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
24578 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24579 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24580 \ -- \ID input divider \ 10 = /4
24581 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24582 \ - \TBCLR TimerB Clear
24585 \ -------------------------------\
24586 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24587 \ -- \CM Capture Mode
24592 \ --- \OUTMOD \ 011 = set/reset
24598 \ -------------------------------\
24600 \ -------------------------------\
24602 \ ------------------------------\
24603 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24604 \ ------------------------------\
24605 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24606 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24607 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
24608 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24610 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
24611 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24613 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24614 \ ------------------------------\
24615 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24616 \ ------------------------------\
24617 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24618 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24619 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24620 \ ------------------------------\
24621 BIS.B #LCDVo,&LCDVo_DIR \
24622 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24623 \ ------------------------------\
24624 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24625 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24626 \ ------------------------------\
24627 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24628 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24629 \ ******************************\
24631 \ ******************************\
24632 BIS.B #RC5,&IR_IE \ enable RC5_Int
24633 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24634 \ ******************************\
24635 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24636 \ ******************************\
24637 \ %01 0001 0100 \ TAxCTL
24638 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24639 \ -- \ ID divided by 1
24640 \ -- \ MC MODE = up to TAxCCRn
24641 \ - \ TACLR clear timer count
24644 \ ------------------------------\
24645 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24646 \ ------------------------------\
24648 \ --- \ TAIDEX pre divisor
24649 \ ------------------------------\
24650 \ %0000 0000 0000 0101 \ TAxCCR0
24651 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24652 \ ------------------------------\
24653 \ %0000 0000 0001 0000 \ TAxCCTL0
24654 \ - \ CAP capture/compare mode = compare
24657 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24658 \ ------------------------------\
24659 \ define LPM mode for ACCEPT \
24660 \ ------------------------------\
24661 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
24662 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24663 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24664 \ ------------------------------\
24666 \ ------------------------------\
24668 \ ------------------------------\
24669 #1000 20_US \ 1- wait 20 ms
24670 %011 TOP_LCD \ 2- send DB5=DB4=1
24671 #205 20_US \ 3- wait 4,1 ms
24672 %011 TOP_LCD \ 4- send again DB5=DB4=1
24673 #5 20_US \ 5- wait 0,1 ms
24674 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24675 #2 20_US \ wait 40 us = LCD cycle
24676 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24677 #2 20_US \ wait 40 us = LCD cycle
24678 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24679 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24680 LCD_CLEAR \ 10- "LCD_Clear"
24681 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24682 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24683 LCD_CLEAR \ 10- "LCD_Clear"
24684 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24685 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24686 CR ." I love you" \ display message on LCD
24687 ['] CR >BODY IS CR \ CR executes its default value
24688 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24689 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24692 \ ------------------------------\
24694 \ ------------------------------\
24695 CODE START \ this routine replaces WARM and COLD default values by these of this application.
24696 \ ------------------------------\
24697 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
24698 0= IF \ if not done, customizes MARKER_DOES
24699 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
24700 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
24701 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
24702 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
24703 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24704 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
24705 MOV #RC5_INT,&IR_VEC \ init interrupt vector
24706 MOV #INI_R2L,PC \ then execute new INI_APP, without return
24710 \ ------------------------------\
24713 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24715 MARKER {RC5TOLCD} \ restore the state before MARKER definition
24716 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
24717 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
24718 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
24719 \ {RC5TOLCD}+14: make room to save previous IR_VEC
24721 [UNDEFINED] CONSTANT [IF]
24722 \ https://forth-standard.org/standard/core/CONSTANT
24723 \ CONSTANT <name> n -- define a Forth CONSTANT
24727 MOV TOS,-2(W) \ PFA = n
24734 [UNDEFINED] STATE [IF]
24735 \ https://forth-standard.org/standard/core/STATE
24736 \ STATE -- a-addr holds compiler state
24737 STATEADR CONSTANT STATE
24741 \ https://forth-standard.org/standard/core/Equal
24742 \ = x1 x2 -- flag test x1=x2
24749 XOR #-1,TOS \ 1 flag Z = 1
24754 [UNDEFINED] IF [IF] \ define IF and THEN
24755 \ https://forth-standard.org/standard/core/IF
24756 \ IF -- IFadr initialize conditional forward branch
24757 CODE IF \ immediate
24760 MOV &DP,TOS \ -- HERE
24761 ADD #4,&DP \ compile one word, reserve one word
24762 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
24763 ADD #2,TOS \ -- HERE+2=IFadr
24767 \ https://forth-standard.org/standard/core/THEN
24768 \ THEN IFadr -- resolve forward branch
24769 CODE THEN \ immediate
24770 MOV &DP,0(TOS) \ -- IFadr
24776 [UNDEFINED] ELSE [IF]
24777 \ https://forth-standard.org/standard/core/ELSE
24778 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
24779 CODE ELSE \ immediate
24780 ADD #4,&DP \ make room to compile two words
24781 MOV &DP,W \ W=HERE+4
24783 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
24785 MOV W,TOS \ -- ELSEadr
24790 [UNDEFINED] IS [IF] \ define DEFER! and IS
24792 \ https://forth-standard.org/standard/core/DEFERStore
24793 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
24794 CODE DEFER! \ xt2 xt1 --
24795 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
24800 \ https://forth-standard.org/standard/core/IS
24803 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
24804 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
24805 \ or in a definition : ... ['] U. IS DISPLAY ...
24806 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
24808 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
24812 IF POSTPONE ['] POSTPONE DEFER!
24818 [UNDEFINED] >BODY [IF]
24819 \ https://forth-standard.org/standard/core/toBODY
24820 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
24827 \ CODE 20uS \ n -- 8MHz version
24828 \ BEGIN \ 4 + 16 ~ loop
24829 \ MOV #39,rDOCON \ 39
24836 \ MOV #XDOCON,rDOCON \ 2
24841 CODE 20_US \ n -- n * 20 us
24842 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24844 BIT #1,&LCD_TIM_CTL \ 3
24845 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24846 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24848 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24853 CODE TOP_LCD \ LCD Sample
24854 \ \ if write : %xxxx_WWWW --
24855 \ \ if read : -- %0000_RRRR
24856 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24857 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24858 0= IF \ write LCD bits pattern
24859 AND.B #LCD_DB,TOS \
24860 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24861 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24864 THEN \ read LCD bits pattern
24867 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24868 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24869 AND.B #LCD_DB,TOS \
24873 CODE LCD_WRC \ char -- Write Char
24874 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24876 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
24877 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
24878 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24879 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24880 COLON \ high level word starts here
24881 TOP_LCD 2 20_US \ write high nibble first
24885 CODE LCD_WRF \ func -- Write Fonction
24886 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24890 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
24891 : LCD_HOME $02 LCD_WRF 100 20_us ;
24893 \ [UNDEFINED] OR [IF]
24895 \ \ https://forth-standard.org/standard/core/OR
24896 \ \ C OR x1 x2 -- x3 logical OR
24904 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
24905 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
24906 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
24907 \ : LCD_FN_SET $20 OR LCD_WrF ;
24908 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
24909 \ : LCD_GOTO $80 OR LCD_WrF ;
24912 \ CODE LCD_RDS \ -- status Read Status
24913 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24914 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24915 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24916 \ COLON \ starts a FORTH word
24917 \ TOP_LCD 2 20_us \ -- %0000_HHHH
24918 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
24919 \ HI2LO \ switch from FORTH to assembler
24920 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
24921 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
24922 \ MOV @RSP+,IP \ restore IP saved by COLON
24926 \ CODE LCD_RDC \ -- char Read Char
24927 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24932 \ ******************************\
24933 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24934 \ ******************************\
24935 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
24936 BIT.B #SW2,&SW2_IN \ test switch S2
24937 0= IF \ case of switch S2 pressed
24938 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
24940 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
24943 BIT.B #SW1,&SW1_IN \ test switch S1 input
24944 0= IF \ case of Switch S1 pressed
24945 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
24947 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
24954 \ ******************************\
24955 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
24956 \ ******************************\
24957 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24958 \ ******************************\
24959 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24960 \ \ SMclock = 8|16|24 MHz
24961 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
24962 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
24963 \ \ SR(9)=new Toggle bit memory (ADD on)
24964 \ ******************************\
24965 \ RC5_FirstStartBitHalfCycle: \
24966 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
24967 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
24968 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
24970 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
24971 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
24973 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
24974 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
24976 MOV #1778,X \ RC5_Period * 1us
24977 MOV #14,W \ count of loop
24979 \ ******************************\
24980 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
24981 \ ******************************\ |
24982 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
24983 \ RC5_Compute_3/4_Period: \ |
24984 RRUM #1,X \ X=1/2 cycle |
24987 ADD X,Y \ Y=3/4 cycle
24988 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
24990 \ ******************************\
24991 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
24992 \ ******************************\
24993 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24994 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
24995 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24996 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24997 SUB #1,W \ decrement count loop
24998 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
24999 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25000 0<> WHILE \ ----> out of loop ----+
25001 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25003 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25004 CMP Y,X \ 1 | cycle time out of bound ?
25005 U>= IF \ 2 ^ | yes:
25006 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25007 GOTO FW1 \ | | quit on truncated RC5 message
25009 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25011 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25012 \ ******************************\ |
25013 \ RC5_SampleEndOf: \ <---------------------+
25014 \ ******************************\
25015 BIC #$30,&RC5_TIM_CTL \ stop timer
25016 \ ******************************\
25017 \ RC5_ComputeNewRC5word \
25018 \ ******************************\
25019 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25020 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25021 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25022 \ ******************************\
25023 \ RC5_ComputeC6bit \
25024 \ ******************************\
25025 BIT #BIT14,T \ test /C6 bit in T
25026 0= IF BIS #BIT6,X \ set C6 bit in X
25027 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25028 \ ******************************\
25029 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25030 \ ******************************\
25031 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
25032 \ ******************************\
25033 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25034 XOR @RSP,T \ (new XOR old) Toggle bits
25035 BIT #UF10,T \ repeated RC5_command ?
25036 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
25037 XOR #UF10,0(RSP) \ 5 toggle bit memory
25038 \ ******************************\
25039 \ Display IR_RC5 code \
25040 \ ******************************\
25041 SUB #8,PSP \ TOS -- x x x x TOS
25042 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25043 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25044 MOV #$10,&BASEADR \ set hexadecimal base
25045 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25046 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25047 LO2HI \ switch from assembler to FORTH
25048 LCD_CLEAR \ set LCD cursor at home
25049 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25050 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25051 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25052 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25053 HI2LO \ -- switch from FORTH to assembler
25054 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25055 MOV @PSP+,TOS \ -- TOS
25057 MOV @RSP+,SR \ restore SR flags
25058 BIC #%1111_1000,SR \ but force CPU Active Mode
25059 RET \ (instead of RETI)
25063 \ ------------------------------\
25064 HDNCODE STOP_R2L \ define new STOP_APP
25065 \ ------------------------------\
25066 CMP #RET_ADR,&{RC5TOLCD}+8 \
25067 0<> IF \ if previous START executing
25068 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
25069 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
25070 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
25071 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
25072 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
25073 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
25074 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
25075 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
25076 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
25077 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
25082 \ ------------------------------\
25084 \ ------------------------------\
25085 BW1 \ <-- INI_R2L for some events
25087 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25089 ." RC5toLCD is removed,"
25090 ." type START to restart"
25093 \ ------------------------------\
25095 \ ------------------------------\
25096 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
25097 \ ------------------------------\
25099 \ ------------------------------\
25100 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
25101 \ ------------------------------\
25102 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
25103 \ ------------------------------\
25104 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
25105 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
25107 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
25108 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
25110 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
25111 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
25112 \ CMP #4,TOS \ hardware RST
25113 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
25114 \ CMP #2,TOS \ Power_ON event
25115 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
25117 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
25119 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
25121 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
25122 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
25123 \ ------------------------------\
25124 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
25125 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25126 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25127 \ -- \ID input divider \ 10 = /4
25128 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25129 \ - \TBCLR TimerB Clear
25132 \ -------------------------------\
25133 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25134 \ -- \CM Capture Mode
25139 \ --- \OUTMOD \ 011 = set/reset
25145 \ -------------------------------\
25147 \ -------------------------------\
25149 \ ------------------------------\
25150 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25151 \ ------------------------------\
25152 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25153 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25154 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
25155 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25157 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
25158 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25160 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
25161 \ ------------------------------\
25162 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25163 \ ------------------------------\
25164 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
25165 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25166 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25167 \ ------------------------------\
25168 BIS.B #LCDVo,&LCDVo_DIR \
25169 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
25170 \ ------------------------------\
25171 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25172 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25173 \ ------------------------------\
25174 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25175 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25176 \ ******************************\
25178 \ ******************************\
25179 BIS.B #RC5,&IR_IE \ enable RC5_Int
25180 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25181 \ ******************************\
25182 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25183 \ ******************************\
25184 \ %01 0001 0100 \ TAxCTL
25185 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
25186 \ -- \ ID divided by 1
25187 \ -- \ MC MODE = up to TAxCCRn
25188 \ - \ TACLR clear timer count
25191 \ ------------------------------\
25192 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
25193 \ ------------------------------\
25195 \ --- \ TAIDEX pre divisor
25196 \ ------------------------------\
25197 \ %0000 0000 0000 0101 \ TAxCCR0
25198 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25199 \ ------------------------------\
25200 \ %0000 0000 0001 0000 \ TAxCCTL0
25201 \ - \ CAP capture/compare mode = compare
25204 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
25205 \ ------------------------------\
25206 \ define LPM mode for ACCEPT \
25207 \ ------------------------------\
25208 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
25209 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25210 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25211 \ ------------------------------\
25213 \ ------------------------------\
25215 \ ------------------------------\
25216 #1000 20_US \ 1- wait 20 ms
25217 %011 TOP_LCD \ 2- send DB5=DB4=1
25218 #205 20_US \ 3- wait 4,1 ms
25219 %011 TOP_LCD \ 4- send again DB5=DB4=1
25220 #5 20_US \ 5- wait 0,1 ms
25221 %011 TOP_LCD \ 6- send again again DB5=DB4=1
25222 #2 20_US \ wait 40 us = LCD cycle
25223 %010 TOP_LCD \ 7- send DB5=1 DB4=0
25224 #2 20_US \ wait 40 us = LCD cycle
25225 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25226 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25227 LCD_CLEAR \ 10- "LCD_Clear"
25228 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25229 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25230 LCD_CLEAR \ 10- "LCD_Clear"
25231 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25232 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25233 CR ." I love you" \ display message on LCD
25234 ['] CR >BODY IS CR \ CR executes its default value
25235 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
25236 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25239 \ ------------------------------\
25241 \ ------------------------------\
25242 CODE START \ this routine replaces WARM and COLD default values by these of this application.
25243 \ ------------------------------\
25244 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
25245 0= IF \ if not done, customizes MARKER_DOES
25246 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
25247 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
25248 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
25249 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
25250 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25251 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
25252 MOV #RC5_INT,&IR_VEC \ init interrupt vector
25253 MOV #INI_R2L,PC \ then execute new INI_APP, without return
25257 \ ------------------------------\
25260 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
25262 MARKER {RC5TOLCD} \ restore the state before MARKER definition
25263 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
25264 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
25265 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
25266 \ {RC5TOLCD}+14: make room to save previous IR_VEC
25268 [UNDEFINED] CONSTANT [IF]
25269 \ https://forth-standard.org/standard/core/CONSTANT
25270 \ CONSTANT <name> n -- define a Forth CONSTANT
25274 MOV TOS,-2(W) \ PFA = n
25281 [UNDEFINED] STATE [IF]
25282 \ https://forth-standard.org/standard/core/STATE
25283 \ STATE -- a-addr holds compiler state
25284 STATEADR CONSTANT STATE
25288 \ https://forth-standard.org/standard/core/Equal
25289 \ = x1 x2 -- flag test x1=x2
25296 XOR #-1,TOS \ 1 flag Z = 1
25301 [UNDEFINED] IF [IF] \ define IF and THEN
25302 \ https://forth-standard.org/standard/core/IF
25303 \ IF -- IFadr initialize conditional forward branch
25304 CODE IF \ immediate
25307 MOV &DP,TOS \ -- HERE
25308 ADD #4,&DP \ compile one word, reserve one word
25309 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
25310 ADD #2,TOS \ -- HERE+2=IFadr
25314 \ https://forth-standard.org/standard/core/THEN
25315 \ THEN IFadr -- resolve forward branch
25316 CODE THEN \ immediate
25317 MOV &DP,0(TOS) \ -- IFadr
25323 [UNDEFINED] ELSE [IF]
25324 \ https://forth-standard.org/standard/core/ELSE
25325 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
25326 CODE ELSE \ immediate
25327 ADD #4,&DP \ make room to compile two words
25328 MOV &DP,W \ W=HERE+4
25330 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
25332 MOV W,TOS \ -- ELSEadr
25337 [UNDEFINED] IS [IF] \ define DEFER! and IS
25339 \ https://forth-standard.org/standard/core/DEFERStore
25340 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
25341 CODE DEFER! \ xt2 xt1 --
25342 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
25347 \ https://forth-standard.org/standard/core/IS
25350 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
25351 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
25352 \ or in a definition : ... ['] U. IS DISPLAY ...
25353 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
25355 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
25359 IF POSTPONE ['] POSTPONE DEFER!
25365 [UNDEFINED] >BODY [IF]
25366 \ https://forth-standard.org/standard/core/toBODY
25367 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
25374 \ CODE 20uS \ n -- 8MHz version
25375 \ BEGIN \ 4 + 16 ~ loop
25376 \ MOV #39,rDOCON \ 39
25383 \ MOV #XDOCON,rDOCON \ 2
25388 CODE 20_US \ n -- n * 20 us
25389 BEGIN \ here we presume that LCD_TIM_IFG = 1...
25391 BIT #1,&LCD_TIM_CTL \ 3
25392 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
25393 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
25395 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
25400 CODE TOP_LCD \ LCD Sample
25401 \ \ if write : %xxxx_WWWW --
25402 \ \ if read : -- %0000_RRRR
25403 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25404 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25405 0= IF \ write LCD bits pattern
25406 AND.B #LCD_DB,TOS \
25407 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25408 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25411 THEN \ read LCD bits pattern
25414 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25415 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25416 AND.B #LCD_DB,TOS \
25420 CODE LCD_WRC \ char -- Write Char
25421 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25423 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
25424 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
25425 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25426 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25427 COLON \ high level word starts here
25428 TOP_LCD 2 20_US \ write high nibble first
25432 CODE LCD_WRF \ func -- Write Fonction
25433 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25437 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
25438 : LCD_HOME $02 LCD_WRF 100 20_us ;
25440 \ [UNDEFINED] OR [IF]
25442 \ \ https://forth-standard.org/standard/core/OR
25443 \ \ C OR x1 x2 -- x3 logical OR
25451 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
25452 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
25453 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
25454 \ : LCD_FN_SET $20 OR LCD_WrF ;
25455 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
25456 \ : LCD_GOTO $80 OR LCD_WrF ;
25459 \ CODE LCD_RDS \ -- status Read Status
25460 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25461 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25462 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25463 \ COLON \ starts a FORTH word
25464 \ TOP_LCD 2 20_us \ -- %0000_HHHH
25465 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
25466 \ HI2LO \ switch from FORTH to assembler
25467 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
25468 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
25469 \ MOV @RSP+,IP \ restore IP saved by COLON
25473 \ CODE LCD_RDC \ -- char Read Char
25474 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25479 \ ******************************\
25480 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25481 \ ******************************\
25482 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
25483 BIT.B #SW2,&SW2_IN \ test switch S2
25484 0= IF \ case of switch S2 pressed
25485 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25487 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
25490 BIT.B #SW1,&SW1_IN \ test switch S1 input
25491 0= IF \ case of Switch S1 pressed
25492 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25494 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25501 \ ******************************\
25502 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
25503 \ ******************************\
25504 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25505 \ ******************************\
25506 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25507 \ \ SMclock = 8|16|24 MHz
25508 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25509 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25510 \ \ SR(9)=new Toggle bit memory (ADD on)
25511 \ ******************************\
25512 \ RC5_FirstStartBitHalfCycle: \
25513 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25514 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
25515 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
25517 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
25518 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
25520 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
25521 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
25523 MOV #1778,X \ RC5_Period * 1us
25524 MOV #14,W \ count of loop
25526 \ ******************************\
25527 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
25528 \ ******************************\ |
25529 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25530 \ RC5_Compute_3/4_Period: \ |
25531 RRUM #1,X \ X=1/2 cycle |
25534 ADD X,Y \ Y=3/4 cycle
25535 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
25537 \ ******************************\
25538 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25539 \ ******************************\
25540 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25541 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
25542 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25543 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25544 SUB #1,W \ decrement count loop
25545 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
25546 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25547 0<> WHILE \ ----> out of loop ----+
25548 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25550 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25551 CMP Y,X \ 1 | cycle time out of bound ?
25552 U>= IF \ 2 ^ | yes:
25553 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25554 GOTO FW1 \ | | quit on truncated RC5 message
25556 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25558 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25559 \ ******************************\ |
25560 \ RC5_SampleEndOf: \ <---------------------+
25561 \ ******************************\
25562 BIC #$30,&RC5_TIM_CTL \ stop timer
25563 \ ******************************\
25564 \ RC5_ComputeNewRC5word \
25565 \ ******************************\
25566 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25567 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25568 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25569 \ ******************************\
25570 \ RC5_ComputeC6bit \
25571 \ ******************************\
25572 BIT #BIT14,T \ test /C6 bit in T
25573 0= IF BIS #BIT6,X \ set C6 bit in X
25574 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25575 \ ******************************\
25576 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25577 \ ******************************\
25578 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
25579 \ ******************************\
25580 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25581 XOR @RSP,T \ (new XOR old) Toggle bits
25582 BIT #UF10,T \ repeated RC5_command ?
25583 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
25584 XOR #UF10,0(RSP) \ 5 toggle bit memory
25585 \ ******************************\
25586 \ Display IR_RC5 code \
25587 \ ******************************\
25588 SUB #8,PSP \ TOS -- x x x x TOS
25589 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25590 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25591 MOV #$10,&BASEADR \ set hexadecimal base
25592 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25593 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25594 LO2HI \ switch from assembler to FORTH
25595 LCD_CLEAR \ set LCD cursor at home
25596 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25597 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25598 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25599 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25600 HI2LO \ -- switch from FORTH to assembler
25601 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25602 MOV @PSP+,TOS \ -- TOS
25604 MOV @RSP+,SR \ restore SR flags
25605 BIC #%1111_1000,SR \ but force CPU Active Mode
25606 RET \ (instead of RETI)
25610 \ ------------------------------\
25611 HDNCODE STOP_R2L \ define new STOP_APP
25612 \ ------------------------------\
25613 CMP #RET_ADR,&{RC5TOLCD}+8 \
25614 0<> IF \ if previous START executing
25615 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
25616 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
25617 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
25618 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
25619 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
25620 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
25621 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
25622 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
25623 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
25624 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
25629 \ ------------------------------\
25631 \ ------------------------------\
25632 BW1 \ <-- INI_R2L for some events
25634 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25636 ." RC5toLCD is removed,"
25637 ." type START to restart"
25640 \ ------------------------------\
25642 \ ------------------------------\
25643 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
25644 \ ------------------------------\
25646 \ ------------------------------\
25647 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
25648 \ ------------------------------\
25649 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
25650 \ ------------------------------\
25651 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
25652 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
25654 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
25655 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
25657 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
25658 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
25659 \ CMP #4,TOS \ hardware RST
25660 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
25661 \ CMP #2,TOS \ Power_ON event
25662 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
25664 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
25666 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
25668 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
25669 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
25670 \ ------------------------------\
25671 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
25672 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25673 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25674 \ -- \ID input divider \ 10 = /4
25675 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25676 \ - \TBCLR TimerB Clear
25679 \ -------------------------------\
25680 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25681 \ -- \CM Capture Mode
25686 \ --- \OUTMOD \ 011 = set/reset
25692 \ -------------------------------\
25694 \ -------------------------------\
25696 \ ------------------------------\
25697 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25698 \ ------------------------------\
25699 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25700 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25701 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
25702 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25704 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
25705 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25707 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
25708 \ ------------------------------\
25709 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25710 \ ------------------------------\
25711 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
25712 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25713 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25714 \ ------------------------------\
25715 BIS.B #LCDVo,&LCDVo_DIR \
25716 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
25717 \ ------------------------------\
25718 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25719 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25720 \ ------------------------------\
25721 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25722 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25723 \ ******************************\
25725 \ ******************************\
25726 BIS.B #RC5,&IR_IE \ enable RC5_Int
25727 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25728 \ ******************************\
25729 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25730 \ ******************************\
25731 \ %01 0001 0100 \ TAxCTL
25732 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
25733 \ -- \ ID divided by 1
25734 \ -- \ MC MODE = up to TAxCCRn
25735 \ - \ TACLR clear timer count
25738 \ ------------------------------\
25739 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
25740 \ ------------------------------\
25742 \ --- \ TAIDEX pre divisor
25743 \ ------------------------------\
25744 \ %0000 0000 0000 0101 \ TAxCCR0
25745 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25746 \ ------------------------------\
25747 \ %0000 0000 0001 0000 \ TAxCCTL0
25748 \ - \ CAP capture/compare mode = compare
25751 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
25752 \ ------------------------------\
25753 \ define LPM mode for ACCEPT \
25754 \ ------------------------------\
25755 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
25756 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25757 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25758 \ ------------------------------\
25760 \ ------------------------------\
25762 \ ------------------------------\
25763 #1000 20_US \ 1- wait 20 ms
25764 %011 TOP_LCD \ 2- send DB5=DB4=1
25765 #205 20_US \ 3- wait 4,1 ms
25766 %011 TOP_LCD \ 4- send again DB5=DB4=1
25767 #5 20_US \ 5- wait 0,1 ms
25768 %011 TOP_LCD \ 6- send again again DB5=DB4=1
25769 #2 20_US \ wait 40 us = LCD cycle
25770 %010 TOP_LCD \ 7- send DB5=1 DB4=0
25771 #2 20_US \ wait 40 us = LCD cycle
25772 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25773 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25774 LCD_CLEAR \ 10- "LCD_Clear"
25775 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25776 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25777 LCD_CLEAR \ 10- "LCD_Clear"
25778 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25779 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25780 CR ." I love you" \ display message on LCD
25781 ['] CR >BODY IS CR \ CR executes its default value
25782 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
25783 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25786 \ ------------------------------\
25788 \ ------------------------------\
25789 CODE START \ this routine replaces WARM and COLD default values by these of this application.
25790 \ ------------------------------\
25791 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
25792 0= IF \ if not done, customizes MARKER_DOES
25793 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
25794 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
25795 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
25796 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
25797 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25798 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
25799 MOV #RC5_INT,&IR_VEC \ init interrupt vector
25800 MOV #INI_R2L,PC \ then execute new INI_APP, without return
25804 \ ------------------------------\
25807 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
25809 MARKER {RC5TOLCD} \ restore the state before MARKER definition
25810 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
25811 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
25812 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
25813 \ {RC5TOLCD}+14: make room to save previous IR_VEC
25815 [UNDEFINED] CONSTANT [IF]
25816 \ https://forth-standard.org/standard/core/CONSTANT
25817 \ CONSTANT <name> n -- define a Forth CONSTANT
25821 MOV TOS,-2(W) \ PFA = n
25828 [UNDEFINED] STATE [IF]
25829 \ https://forth-standard.org/standard/core/STATE
25830 \ STATE -- a-addr holds compiler state
25831 STATEADR CONSTANT STATE
25835 \ https://forth-standard.org/standard/core/Equal
25836 \ = x1 x2 -- flag test x1=x2
25843 XOR #-1,TOS \ 1 flag Z = 1
25848 [UNDEFINED] IF [IF] \ define IF and THEN
25849 \ https://forth-standard.org/standard/core/IF
25850 \ IF -- IFadr initialize conditional forward branch
25851 CODE IF \ immediate
25854 MOV &DP,TOS \ -- HERE
25855 ADD #4,&DP \ compile one word, reserve one word
25856 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
25857 ADD #2,TOS \ -- HERE+2=IFadr
25861 \ https://forth-standard.org/standard/core/THEN
25862 \ THEN IFadr -- resolve forward branch
25863 CODE THEN \ immediate
25864 MOV &DP,0(TOS) \ -- IFadr
25870 [UNDEFINED] ELSE [IF]
25871 \ https://forth-standard.org/standard/core/ELSE
25872 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
25873 CODE ELSE \ immediate
25874 ADD #4,&DP \ make room to compile two words
25875 MOV &DP,W \ W=HERE+4
25877 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
25879 MOV W,TOS \ -- ELSEadr
25884 [UNDEFINED] IS [IF] \ define DEFER! and IS
25886 \ https://forth-standard.org/standard/core/DEFERStore
25887 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
25888 CODE DEFER! \ xt2 xt1 --
25889 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
25894 \ https://forth-standard.org/standard/core/IS
25897 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
25898 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
25899 \ or in a definition : ... ['] U. IS DISPLAY ...
25900 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
25902 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
25906 IF POSTPONE ['] POSTPONE DEFER!
25912 [UNDEFINED] >BODY [IF]
25913 \ https://forth-standard.org/standard/core/toBODY
25914 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
25921 \ CODE 20uS \ n -- 8MHz version
25922 \ BEGIN \ 4 + 16 ~ loop
25923 \ MOV #39,rDOCON \ 39
25930 \ MOV #XDOCON,rDOCON \ 2
25935 CODE 20_US \ n -- n * 20 us
25936 BEGIN \ here we presume that LCD_TIM_IFG = 1...
25938 BIT #1,&LCD_TIM_CTL \ 3
25939 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
25940 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
25942 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
25947 CODE TOP_LCD \ LCD Sample
25948 \ \ if write : %xxxx_WWWW --
25949 \ \ if read : -- %0000_RRRR
25950 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25951 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25952 0= IF \ write LCD bits pattern
25953 AND.B #LCD_DB,TOS \
25954 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25955 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25958 THEN \ read LCD bits pattern
25961 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25962 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25963 AND.B #LCD_DB,TOS \
25967 CODE LCD_WRC \ char -- Write Char
25968 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25970 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
25971 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
25972 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25973 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25974 COLON \ high level word starts here
25975 TOP_LCD 2 20_US \ write high nibble first
25979 CODE LCD_WRF \ func -- Write Fonction
25980 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25984 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
25985 : LCD_HOME $02 LCD_WRF 100 20_us ;
25987 \ [UNDEFINED] OR [IF]
25989 \ \ https://forth-standard.org/standard/core/OR
25990 \ \ C OR x1 x2 -- x3 logical OR
25998 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
25999 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
26000 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
26001 \ : LCD_FN_SET $20 OR LCD_WrF ;
26002 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
26003 \ : LCD_GOTO $80 OR LCD_WrF ;
26006 \ CODE LCD_RDS \ -- status Read Status
26007 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26008 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26009 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26010 \ COLON \ starts a FORTH word
26011 \ TOP_LCD 2 20_us \ -- %0000_HHHH
26012 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
26013 \ HI2LO \ switch from FORTH to assembler
26014 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
26015 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
26016 \ MOV @RSP+,IP \ restore IP saved by COLON
26020 \ CODE LCD_RDC \ -- char Read Char
26021 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26026 \ ******************************\
26027 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26028 \ ******************************\
26029 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
26030 BIT.B #SW2,&SW2_IN \ test switch S2
26031 0= IF \ case of switch S2 pressed
26032 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26034 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
26037 BIT.B #SW1,&SW1_IN \ test switch S1 input
26038 0= IF \ case of Switch S1 pressed
26039 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26041 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26048 \ ******************************\
26049 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
26050 \ ******************************\
26051 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26052 \ ******************************\
26053 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26054 \ \ SMclock = 8|16|24 MHz
26055 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26056 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26057 \ \ SR(9)=new Toggle bit memory (ADD on)
26058 \ ******************************\
26059 \ RC5_FirstStartBitHalfCycle: \
26060 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26061 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
26062 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
26064 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
26065 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
26067 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
26068 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
26070 MOV #1778,X \ RC5_Period * 1us
26071 MOV #14,W \ count of loop
26073 \ ******************************\
26074 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
26075 \ ******************************\ |
26076 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26077 \ RC5_Compute_3/4_Period: \ |
26078 RRUM #1,X \ X=1/2 cycle |
26081 ADD X,Y \ Y=3/4 cycle
26082 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
26084 \ ******************************\
26085 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26086 \ ******************************\
26087 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26088 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
26089 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26090 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26091 SUB #1,W \ decrement count loop
26092 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
26093 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26094 0<> WHILE \ ----> out of loop ----+
26095 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26097 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
26098 CMP Y,X \ 1 | cycle time out of bound ?
26099 U>= IF \ 2 ^ | yes:
26100 BIC #$30,&RC5_TIM_CTL \ | | stop timer
26101 GOTO FW1 \ | | quit on truncated RC5 message
26103 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
26105 REPEAT \ ----> loop back --+ | with X = new RC5_period value
26106 \ ******************************\ |
26107 \ RC5_SampleEndOf: \ <---------------------+
26108 \ ******************************\
26109 BIC #$30,&RC5_TIM_CTL \ stop timer
26110 \ ******************************\
26111 \ RC5_ComputeNewRC5word \
26112 \ ******************************\
26113 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
26114 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
26115 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
26116 \ ******************************\
26117 \ RC5_ComputeC6bit \
26118 \ ******************************\
26119 BIT #BIT14,T \ test /C6 bit in T
26120 0= IF BIS #BIT6,X \ set C6 bit in X
26121 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
26122 \ ******************************\
26123 \ RC5_CommandByteIsDone \ -- BASE RC5_code
26124 \ ******************************\
26125 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
26126 \ ******************************\
26127 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
26128 XOR @RSP,T \ (new XOR old) Toggle bits
26129 BIT #UF10,T \ repeated RC5_command ?
26130 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
26131 XOR #UF10,0(RSP) \ 5 toggle bit memory
26132 \ ******************************\
26133 \ Display IR_RC5 code \
26134 \ ******************************\
26135 SUB #8,PSP \ TOS -- x x x x TOS
26136 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
26137 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
26138 MOV #$10,&BASEADR \ set hexadecimal base
26139 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
26140 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
26141 LO2HI \ switch from assembler to FORTH
26142 LCD_CLEAR \ set LCD cursor at home
26143 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
26144 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
26145 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
26146 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
26147 HI2LO \ -- switch from FORTH to assembler
26148 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
26149 MOV @PSP+,TOS \ -- TOS
26151 MOV @RSP+,SR \ restore SR flags
26152 BIC #%1111_1000,SR \ but force CPU Active Mode
26153 RET \ (instead of RETI)
26157 \ ------------------------------\
26158 HDNCODE STOP_R2L \ define new STOP_APP
26159 \ ------------------------------\
26160 CMP #RET_ADR,&{RC5TOLCD}+8 \
26161 0<> IF \ if previous START executing
26162 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
26163 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
26164 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
26165 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
26166 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
26167 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
26168 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
26169 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
26170 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
26171 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
26176 \ ------------------------------\
26178 \ ------------------------------\
26179 BW1 \ <-- INI_R2L for some events
26181 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
26183 ." RC5toLCD is removed,"
26184 ." type START to restart"
26187 \ ------------------------------\
26189 \ ------------------------------\
26190 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
26191 \ ------------------------------\
26193 \ ------------------------------\
26194 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
26195 \ ------------------------------\
26196 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
26197 \ ------------------------------\
26198 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
26199 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
26201 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
26202 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
26204 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
26205 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
26206 \ CMP #4,TOS \ hardware RST
26207 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
26208 \ CMP #2,TOS \ Power_ON event
26209 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
26211 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
26213 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
26215 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
26216 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
26217 \ ------------------------------\
26218 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
26219 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26220 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26221 \ -- \ID input divider \ 10 = /4
26222 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26223 \ - \TBCLR TimerB Clear
26226 \ -------------------------------\
26227 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26228 \ -- \CM Capture Mode
26233 \ --- \OUTMOD \ 011 = set/reset
26239 \ -------------------------------\
26241 \ -------------------------------\
26243 \ ------------------------------\
26244 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26245 \ ------------------------------\
26246 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26247 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26248 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
26249 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26251 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
26252 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26254 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
26255 \ ------------------------------\
26256 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26257 \ ------------------------------\
26258 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
26259 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26260 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26261 \ ------------------------------\
26262 BIS.B #LCDVo,&LCDVo_DIR \
26263 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
26264 \ ------------------------------\
26265 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26266 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26267 \ ------------------------------\
26268 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26269 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26270 \ ******************************\
26272 \ ******************************\
26273 BIS.B #RC5,&IR_IE \ enable RC5_Int
26274 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26275 \ ******************************\
26276 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26277 \ ******************************\
26278 \ %01 0001 0100 \ TAxCTL
26279 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
26280 \ -- \ ID divided by 1
26281 \ -- \ MC MODE = up to TAxCCRn
26282 \ - \ TACLR clear timer count
26285 \ ------------------------------\
26286 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
26287 \ ------------------------------\
26289 \ --- \ TAIDEX pre divisor
26290 \ ------------------------------\
26291 \ %0000 0000 0000 0101 \ TAxCCR0
26292 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26293 \ ------------------------------\
26294 \ %0000 0000 0001 0000 \ TAxCCTL0
26295 \ - \ CAP capture/compare mode = compare
26298 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
26299 \ ------------------------------\
26300 \ define LPM mode for ACCEPT \
26301 \ ------------------------------\
26302 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
26303 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26304 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26305 \ ------------------------------\
26307 \ ------------------------------\
26309 \ ------------------------------\
26310 #1000 20_US \ 1- wait 20 ms
26311 %011 TOP_LCD \ 2- send DB5=DB4=1
26312 #205 20_US \ 3- wait 4,1 ms
26313 %011 TOP_LCD \ 4- send again DB5=DB4=1
26314 #5 20_US \ 5- wait 0,1 ms
26315 %011 TOP_LCD \ 6- send again again DB5=DB4=1
26316 #2 20_US \ wait 40 us = LCD cycle
26317 %010 TOP_LCD \ 7- send DB5=1 DB4=0
26318 #2 20_US \ wait 40 us = LCD cycle
26319 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26320 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26321 LCD_CLEAR \ 10- "LCD_Clear"
26322 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26323 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26324 LCD_CLEAR \ 10- "LCD_Clear"
26325 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26326 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26327 CR ." I love you" \ display message on LCD
26328 ['] CR >BODY IS CR \ CR executes its default value
26329 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
26330 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26333 \ ------------------------------\
26335 \ ------------------------------\
26336 CODE START \ this routine replaces WARM and COLD default values by these of this application.
26337 \ ------------------------------\
26338 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
26339 0= IF \ if not done, customizes MARKER_DOES
26340 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
26341 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
26342 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
26343 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
26344 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26345 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
26346 MOV #RC5_INT,&IR_VEC \ init interrupt vector
26347 MOV #INI_R2L,PC \ then execute new INI_APP, without return
26351 \ ------------------------------\
26354 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26356 MARKER {RC5TOLCD} \ restore the state before MARKER definition
26357 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
26358 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
26359 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
26360 \ {RC5TOLCD}+14: make room to save previous IR_VEC
26362 [UNDEFINED] CONSTANT [IF]
26363 \ https://forth-standard.org/standard/core/CONSTANT
26364 \ CONSTANT <name> n -- define a Forth CONSTANT
26368 MOV TOS,-2(W) \ PFA = n
26375 [UNDEFINED] STATE [IF]
26376 \ https://forth-standard.org/standard/core/STATE
26377 \ STATE -- a-addr holds compiler state
26378 STATEADR CONSTANT STATE
26382 \ https://forth-standard.org/standard/core/Equal
26383 \ = x1 x2 -- flag test x1=x2
26390 XOR #-1,TOS \ 1 flag Z = 1
26395 [UNDEFINED] IF [IF] \ define IF and THEN
26396 \ https://forth-standard.org/standard/core/IF
26397 \ IF -- IFadr initialize conditional forward branch
26398 CODE IF \ immediate
26401 MOV &DP,TOS \ -- HERE
26402 ADD #4,&DP \ compile one word, reserve one word
26403 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
26404 ADD #2,TOS \ -- HERE+2=IFadr
26408 \ https://forth-standard.org/standard/core/THEN
26409 \ THEN IFadr -- resolve forward branch
26410 CODE THEN \ immediate
26411 MOV &DP,0(TOS) \ -- IFadr
26417 [UNDEFINED] ELSE [IF]
26418 \ https://forth-standard.org/standard/core/ELSE
26419 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
26420 CODE ELSE \ immediate
26421 ADD #4,&DP \ make room to compile two words
26422 MOV &DP,W \ W=HERE+4
26424 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
26426 MOV W,TOS \ -- ELSEadr
26431 [UNDEFINED] IS [IF] \ define DEFER! and IS
26433 \ https://forth-standard.org/standard/core/DEFERStore
26434 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
26435 CODE DEFER! \ xt2 xt1 --
26436 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
26441 \ https://forth-standard.org/standard/core/IS
26444 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
26445 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
26446 \ or in a definition : ... ['] U. IS DISPLAY ...
26447 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
26449 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
26453 IF POSTPONE ['] POSTPONE DEFER!
26459 [UNDEFINED] >BODY [IF]
26460 \ https://forth-standard.org/standard/core/toBODY
26461 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
26468 \ CODE 20uS \ n -- 8MHz version
26469 \ BEGIN \ 4 + 16 ~ loop
26470 \ MOV #39,rDOCON \ 39
26477 \ MOV #XDOCON,rDOCON \ 2
26482 CODE 20_US \ n -- n * 20 us
26483 BEGIN \ here we presume that LCD_TIM_IFG = 1...
26485 BIT #1,&LCD_TIM_CTL \ 3
26486 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
26487 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
26489 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
26494 CODE TOP_LCD \ LCD Sample
26495 \ \ if write : %xxxx_WWWW --
26496 \ \ if read : -- %0000_RRRR
26497 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26498 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26499 0= IF \ write LCD bits pattern
26500 AND.B #LCD_DB,TOS \
26501 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26502 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26505 THEN \ read LCD bits pattern
26508 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26509 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26510 AND.B #LCD_DB,TOS \
26514 CODE LCD_WRC \ char -- Write Char
26515 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26517 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
26518 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
26519 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26520 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26521 COLON \ high level word starts here
26522 TOP_LCD 2 20_US \ write high nibble first
26526 CODE LCD_WRF \ func -- Write Fonction
26527 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26531 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
26532 : LCD_HOME $02 LCD_WRF 100 20_us ;
26534 \ [UNDEFINED] OR [IF]
26536 \ \ https://forth-standard.org/standard/core/OR
26537 \ \ C OR x1 x2 -- x3 logical OR
26545 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
26546 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
26547 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
26548 \ : LCD_FN_SET $20 OR LCD_WrF ;
26549 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
26550 \ : LCD_GOTO $80 OR LCD_WrF ;
26553 \ CODE LCD_RDS \ -- status Read Status
26554 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26555 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26556 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26557 \ COLON \ starts a FORTH word
26558 \ TOP_LCD 2 20_us \ -- %0000_HHHH
26559 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
26560 \ HI2LO \ switch from FORTH to assembler
26561 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
26562 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
26563 \ MOV @RSP+,IP \ restore IP saved by COLON
26567 \ CODE LCD_RDC \ -- char Read Char
26568 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26573 \ ******************************\
26574 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26575 \ ******************************\
26576 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
26577 BIT.B #SW2,&SW2_IN \ test switch S2
26578 0= IF \ case of switch S2 pressed
26579 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26581 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
26584 BIT.B #SW1,&SW1_IN \ test switch S1 input
26585 0= IF \ case of Switch S1 pressed
26586 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26588 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26595 \ ******************************\
26596 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
26597 \ ******************************\
26598 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26599 \ ******************************\
26600 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26601 \ \ SMclock = 8|16|24 MHz
26602 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26603 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26604 \ \ SR(9)=new Toggle bit memory (ADD on)
26605 \ ******************************\
26606 \ RC5_FirstStartBitHalfCycle: \
26607 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26608 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
26609 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
26611 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
26612 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
26614 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
26615 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
26617 MOV #1778,X \ RC5_Period * 1us
26618 MOV #14,W \ count of loop
26620 \ ******************************\
26621 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
26622 \ ******************************\ |
26623 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26624 \ RC5_Compute_3/4_Period: \ |
26625 RRUM #1,X \ X=1/2 cycle |
26628 ADD X,Y \ Y=3/4 cycle
26629 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
26631 \ ******************************\
26632 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26633 \ ******************************\
26634 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26635 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
26636 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26637 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26638 SUB #1,W \ decrement count loop
26639 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
26640 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26641 0<> WHILE \ ----> out of loop ----+
26642 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26644 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
26645 CMP Y,X \ 1 | cycle time out of bound ?
26646 U>= IF \ 2 ^ | yes:
26647 BIC #$30,&RC5_TIM_CTL \ | | stop timer
26648 GOTO FW1 \ | | quit on truncated RC5 message
26650 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
26652 REPEAT \ ----> loop back --+ | with X = new RC5_period value
26653 \ ******************************\ |
26654 \ RC5_SampleEndOf: \ <---------------------+
26655 \ ******************************\
26656 BIC #$30,&RC5_TIM_CTL \ stop timer
26657 \ ******************************\
26658 \ RC5_ComputeNewRC5word \
26659 \ ******************************\
26660 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
26661 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
26662 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
26663 \ ******************************\
26664 \ RC5_ComputeC6bit \
26665 \ ******************************\
26666 BIT #BIT14,T \ test /C6 bit in T
26667 0= IF BIS #BIT6,X \ set C6 bit in X
26668 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
26669 \ ******************************\
26670 \ RC5_CommandByteIsDone \ -- BASE RC5_code
26671 \ ******************************\
26672 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
26673 \ ******************************\
26674 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
26675 XOR @RSP,T \ (new XOR old) Toggle bits
26676 BIT #UF10,T \ repeated RC5_command ?
26677 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
26678 XOR #UF10,0(RSP) \ 5 toggle bit memory
26679 \ ******************************\
26680 \ Display IR_RC5 code \
26681 \ ******************************\
26682 SUB #8,PSP \ TOS -- x x x x TOS
26683 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
26684 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
26685 MOV #$10,&BASEADR \ set hexadecimal base
26686 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
26687 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
26688 LO2HI \ switch from assembler to FORTH
26689 LCD_CLEAR \ set LCD cursor at home
26690 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
26691 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
26692 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
26693 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
26694 HI2LO \ -- switch from FORTH to assembler
26695 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
26696 MOV @PSP+,TOS \ -- TOS
26698 MOV @RSP+,SR \ restore SR flags
26699 BIC #%1111_1000,SR \ but force CPU Active Mode
26700 RET \ (instead of RETI)
26704 \ ------------------------------\
26705 HDNCODE STOP_R2L \ define new STOP_APP
26706 \ ------------------------------\
26707 CMP #RET_ADR,&{RC5TOLCD}+8 \
26708 0<> IF \ if previous START executing
26709 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
26710 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
26711 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
26712 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
26713 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
26714 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
26715 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
26716 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
26717 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
26718 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
26723 \ ------------------------------\
26725 \ ------------------------------\
26726 BW1 \ <-- INI_R2L for some events
26728 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
26730 ." RC5toLCD is removed,"
26731 ." type START to restart"
26734 \ ------------------------------\
26736 \ ------------------------------\
26737 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
26738 \ ------------------------------\
26740 \ ------------------------------\
26741 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
26742 \ ------------------------------\
26743 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
26744 \ ------------------------------\
26745 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
26746 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
26748 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
26749 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
26751 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
26752 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
26753 \ CMP #4,TOS \ hardware RST
26754 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
26755 \ CMP #2,TOS \ Power_ON event
26756 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
26758 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
26760 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
26762 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
26763 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
26764 \ ------------------------------\
26765 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
26766 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26767 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26768 \ -- \ID input divider \ 10 = /4
26769 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26770 \ - \TBCLR TimerB Clear
26773 \ -------------------------------\
26774 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26775 \ -- \CM Capture Mode
26780 \ --- \OUTMOD \ 011 = set/reset
26786 \ -------------------------------\
26788 \ -------------------------------\
26790 \ ------------------------------\
26791 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26792 \ ------------------------------\
26793 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26794 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26795 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
26796 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26798 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
26799 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26801 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
26802 \ ------------------------------\
26803 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26804 \ ------------------------------\
26805 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
26806 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26807 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26808 \ ------------------------------\
26809 BIS.B #LCDVo,&LCDVo_DIR \
26810 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
26811 \ ------------------------------\
26812 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26813 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26814 \ ------------------------------\
26815 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26816 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26817 \ ******************************\
26819 \ ******************************\
26820 BIS.B #RC5,&IR_IE \ enable RC5_Int
26821 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26822 \ ******************************\
26823 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26824 \ ******************************\
26825 \ %01 0001 0100 \ TAxCTL
26826 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
26827 \ -- \ ID divided by 1
26828 \ -- \ MC MODE = up to TAxCCRn
26829 \ - \ TACLR clear timer count
26832 \ ------------------------------\
26833 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
26834 \ ------------------------------\
26836 \ --- \ TAIDEX pre divisor
26837 \ ------------------------------\
26838 \ %0000 0000 0000 0101 \ TAxCCR0
26839 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26840 \ ------------------------------\
26841 \ %0000 0000 0001 0000 \ TAxCCTL0
26842 \ - \ CAP capture/compare mode = compare
26845 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
26846 \ ------------------------------\
26847 \ define LPM mode for ACCEPT \
26848 \ ------------------------------\
26849 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
26850 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26851 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26852 \ ------------------------------\
26854 \ ------------------------------\
26856 \ ------------------------------\
26857 #1000 20_US \ 1- wait 20 ms
26858 %011 TOP_LCD \ 2- send DB5=DB4=1
26859 #205 20_US \ 3- wait 4,1 ms
26860 %011 TOP_LCD \ 4- send again DB5=DB4=1
26861 #5 20_US \ 5- wait 0,1 ms
26862 %011 TOP_LCD \ 6- send again again DB5=DB4=1
26863 #2 20_US \ wait 40 us = LCD cycle
26864 %010 TOP_LCD \ 7- send DB5=1 DB4=0
26865 #2 20_US \ wait 40 us = LCD cycle
26866 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26867 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26868 LCD_CLEAR \ 10- "LCD_Clear"
26869 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26870 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26871 LCD_CLEAR \ 10- "LCD_Clear"
26872 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26873 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26874 CR ." I love you" \ display message on LCD
26875 ['] CR >BODY IS CR \ CR executes its default value
26876 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
26877 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26880 \ ------------------------------\
26882 \ ------------------------------\
26883 CODE START \ this routine replaces WARM and COLD default values by these of this application.
26884 \ ------------------------------\
26885 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
26886 0= IF \ if not done, customizes MARKER_DOES
26887 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
26888 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
26889 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
26890 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
26891 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26892 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
26893 MOV #RC5_INT,&IR_VEC \ init interrupt vector
26894 MOV #INI_R2L,PC \ then execute new INI_APP, without return
26898 \ ------------------------------\
26901 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26903 MARKER {RC5TOLCD} \ restore the state before MARKER definition
26904 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
26905 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
26906 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
26907 \ {RC5TOLCD}+14: make room to save previous IR_VEC
26909 [UNDEFINED] CONSTANT [IF]
26910 \ https://forth-standard.org/standard/core/CONSTANT
26911 \ CONSTANT <name> n -- define a Forth CONSTANT
26915 MOV TOS,-2(W) \ PFA = n
26922 [UNDEFINED] STATE [IF]
26923 \ https://forth-standard.org/standard/core/STATE
26924 \ STATE -- a-addr holds compiler state
26925 STATEADR CONSTANT STATE
26929 \ https://forth-standard.org/standard/core/Equal
26930 \ = x1 x2 -- flag test x1=x2
26937 XOR #-1,TOS \ 1 flag Z = 1
26942 [UNDEFINED] IF [IF] \ define IF and THEN
26943 \ https://forth-standard.org/standard/core/IF
26944 \ IF -- IFadr initialize conditional forward branch
26945 CODE IF \ immediate
26948 MOV &DP,TOS \ -- HERE
26949 ADD #4,&DP \ compile one word, reserve one word
26950 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
26951 ADD #2,TOS \ -- HERE+2=IFadr
26955 \ https://forth-standard.org/standard/core/THEN
26956 \ THEN IFadr -- resolve forward branch
26957 CODE THEN \ immediate
26958 MOV &DP,0(TOS) \ -- IFadr
26964 [UNDEFINED] ELSE [IF]
26965 \ https://forth-standard.org/standard/core/ELSE
26966 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
26967 CODE ELSE \ immediate
26968 ADD #4,&DP \ make room to compile two words
26969 MOV &DP,W \ W=HERE+4
26971 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
26973 MOV W,TOS \ -- ELSEadr
26978 [UNDEFINED] IS [IF] \ define DEFER! and IS
26980 \ https://forth-standard.org/standard/core/DEFERStore
26981 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
26982 CODE DEFER! \ xt2 xt1 --
26983 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
26988 \ https://forth-standard.org/standard/core/IS
26991 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
26992 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
26993 \ or in a definition : ... ['] U. IS DISPLAY ...
26994 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
26996 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
27000 IF POSTPONE ['] POSTPONE DEFER!
27006 [UNDEFINED] >BODY [IF]
27007 \ https://forth-standard.org/standard/core/toBODY
27008 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
27015 \ CODE 20uS \ n -- 8MHz version
27016 \ BEGIN \ 4 + 16 ~ loop
27017 \ MOV #39,rDOCON \ 39
27024 \ MOV #XDOCON,rDOCON \ 2
27029 CODE 20_US \ n -- n * 20 us
27030 BEGIN \ here we presume that LCD_TIM_IFG = 1...
27032 BIT #1,&LCD_TIM_CTL \ 3
27033 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
27034 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
27036 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
27041 CODE TOP_LCD \ LCD Sample
27042 \ \ if write : %xxxx_WWWW --
27043 \ \ if read : -- %0000_RRRR
27044 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27045 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27046 0= IF \ write LCD bits pattern
27047 AND.B #LCD_DB,TOS \
27048 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27049 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27052 THEN \ read LCD bits pattern
27055 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27056 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27057 AND.B #LCD_DB,TOS \
27061 CODE LCD_WRC \ char -- Write Char
27062 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27064 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
27065 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
27066 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27067 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27068 COLON \ high level word starts here
27069 TOP_LCD 2 20_US \ write high nibble first
27073 CODE LCD_WRF \ func -- Write Fonction
27074 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27078 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
27079 : LCD_HOME $02 LCD_WRF 100 20_us ;
27081 \ [UNDEFINED] OR [IF]
27083 \ \ https://forth-standard.org/standard/core/OR
27084 \ \ C OR x1 x2 -- x3 logical OR
27092 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
27093 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
27094 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
27095 \ : LCD_FN_SET $20 OR LCD_WrF ;
27096 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
27097 \ : LCD_GOTO $80 OR LCD_WrF ;
27100 \ CODE LCD_RDS \ -- status Read Status
27101 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27102 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27103 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27104 \ COLON \ starts a FORTH word
27105 \ TOP_LCD 2 20_us \ -- %0000_HHHH
27106 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
27107 \ HI2LO \ switch from FORTH to assembler
27108 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
27109 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
27110 \ MOV @RSP+,IP \ restore IP saved by COLON
27114 \ CODE LCD_RDC \ -- char Read Char
27115 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27120 \ ******************************\
27121 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27122 \ ******************************\
27123 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
27124 BIT.B #SW2,&SW2_IN \ test switch S2
27125 0= IF \ case of switch S2 pressed
27126 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27128 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
27131 BIT.B #SW1,&SW1_IN \ test switch S1 input
27132 0= IF \ case of Switch S1 pressed
27133 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27135 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27142 \ ******************************\
27143 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
27144 \ ******************************\
27145 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27146 \ ******************************\
27147 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27148 \ \ SMclock = 8|16|24 MHz
27149 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27150 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27151 \ \ SR(9)=new Toggle bit memory (ADD on)
27152 \ ******************************\
27153 \ RC5_FirstStartBitHalfCycle: \
27154 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27155 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
27156 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
27158 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
27159 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
27161 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
27162 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
27164 MOV #1778,X \ RC5_Period * 1us
27165 MOV #14,W \ count of loop
27167 \ ******************************\
27168 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
27169 \ ******************************\ |
27170 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27171 \ RC5_Compute_3/4_Period: \ |
27172 RRUM #1,X \ X=1/2 cycle |
27175 ADD X,Y \ Y=3/4 cycle
27176 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
27178 \ ******************************\
27179 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27180 \ ******************************\
27181 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27182 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
27183 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27184 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27185 SUB #1,W \ decrement count loop
27186 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
27187 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27188 0<> WHILE \ ----> out of loop ----+
27189 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27191 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
27192 CMP Y,X \ 1 | cycle time out of bound ?
27193 U>= IF \ 2 ^ | yes:
27194 BIC #$30,&RC5_TIM_CTL \ | | stop timer
27195 GOTO FW1 \ | | quit on truncated RC5 message
27197 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
27199 REPEAT \ ----> loop back --+ | with X = new RC5_period value
27200 \ ******************************\ |
27201 \ RC5_SampleEndOf: \ <---------------------+
27202 \ ******************************\
27203 BIC #$30,&RC5_TIM_CTL \ stop timer
27204 \ ******************************\
27205 \ RC5_ComputeNewRC5word \
27206 \ ******************************\
27207 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
27208 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27209 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27210 \ ******************************\
27211 \ RC5_ComputeC6bit \
27212 \ ******************************\
27213 BIT #BIT14,T \ test /C6 bit in T
27214 0= IF BIS #BIT6,X \ set C6 bit in X
27215 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27216 \ ******************************\
27217 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27218 \ ******************************\
27219 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
27220 \ ******************************\
27221 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27222 XOR @RSP,T \ (new XOR old) Toggle bits
27223 BIT #UF10,T \ repeated RC5_command ?
27224 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
27225 XOR #UF10,0(RSP) \ 5 toggle bit memory
27226 \ ******************************\
27227 \ Display IR_RC5 code \
27228 \ ******************************\
27229 SUB #8,PSP \ TOS -- x x x x TOS
27230 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27231 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27232 MOV #$10,&BASEADR \ set hexadecimal base
27233 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27234 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27235 LO2HI \ switch from assembler to FORTH
27236 LCD_CLEAR \ set LCD cursor at home
27237 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27238 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27239 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27240 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27241 HI2LO \ -- switch from FORTH to assembler
27242 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27243 MOV @PSP+,TOS \ -- TOS
27245 MOV @RSP+,SR \ restore SR flags
27246 BIC #%1111_1000,SR \ but force CPU Active Mode
27247 RET \ (instead of RETI)
27251 \ ------------------------------\
27252 HDNCODE STOP_R2L \ define new STOP_APP
27253 \ ------------------------------\
27254 CMP #RET_ADR,&{RC5TOLCD}+8 \
27255 0<> IF \ if previous START executing
27256 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
27257 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
27258 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
27259 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
27260 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
27261 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
27262 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
27263 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
27264 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
27265 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
27270 \ ------------------------------\
27272 \ ------------------------------\
27273 BW1 \ <-- INI_R2L for some events
27275 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
27277 ." RC5toLCD is removed,"
27278 ." type START to restart"
27281 \ ------------------------------\
27283 \ ------------------------------\
27284 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
27285 \ ------------------------------\
27287 \ ------------------------------\
27288 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
27289 \ ------------------------------\
27290 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
27291 \ ------------------------------\
27292 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
27293 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
27295 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
27296 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
27298 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
27299 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
27300 \ CMP #4,TOS \ hardware RST
27301 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
27302 \ CMP #2,TOS \ Power_ON event
27303 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
27305 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
27307 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
27309 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
27310 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
27311 \ ------------------------------\
27312 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
27313 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27314 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27315 \ -- \ID input divider \ 10 = /4
27316 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27317 \ - \TBCLR TimerB Clear
27320 \ -------------------------------\
27321 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27322 \ -- \CM Capture Mode
27327 \ --- \OUTMOD \ 011 = set/reset
27333 \ -------------------------------\
27335 \ -------------------------------\
27337 \ ------------------------------\
27338 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27339 \ ------------------------------\
27340 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27341 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27342 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
27343 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27345 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
27346 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27348 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
27349 \ ------------------------------\
27350 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27351 \ ------------------------------\
27352 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
27353 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27354 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27355 \ ------------------------------\
27356 BIS.B #LCDVo,&LCDVo_DIR \
27357 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
27358 \ ------------------------------\
27359 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27360 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27361 \ ------------------------------\
27362 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27363 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27364 \ ******************************\
27366 \ ******************************\
27367 BIS.B #RC5,&IR_IE \ enable RC5_Int
27368 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27369 \ ******************************\
27370 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27371 \ ******************************\
27372 \ %01 0001 0100 \ TAxCTL
27373 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
27374 \ -- \ ID divided by 1
27375 \ -- \ MC MODE = up to TAxCCRn
27376 \ - \ TACLR clear timer count
27379 \ ------------------------------\
27380 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
27381 \ ------------------------------\
27383 \ --- \ TAIDEX pre divisor
27384 \ ------------------------------\
27385 \ %0000 0000 0000 0101 \ TAxCCR0
27386 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27387 \ ------------------------------\
27388 \ %0000 0000 0001 0000 \ TAxCCTL0
27389 \ - \ CAP capture/compare mode = compare
27392 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
27393 \ ------------------------------\
27394 \ define LPM mode for ACCEPT \
27395 \ ------------------------------\
27396 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
27397 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27398 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27399 \ ------------------------------\
27401 \ ------------------------------\
27403 \ ------------------------------\
27404 #1000 20_US \ 1- wait 20 ms
27405 %011 TOP_LCD \ 2- send DB5=DB4=1
27406 #205 20_US \ 3- wait 4,1 ms
27407 %011 TOP_LCD \ 4- send again DB5=DB4=1
27408 #5 20_US \ 5- wait 0,1 ms
27409 %011 TOP_LCD \ 6- send again again DB5=DB4=1
27410 #2 20_US \ wait 40 us = LCD cycle
27411 %010 TOP_LCD \ 7- send DB5=1 DB4=0
27412 #2 20_US \ wait 40 us = LCD cycle
27413 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27414 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27415 LCD_CLEAR \ 10- "LCD_Clear"
27416 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27417 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27418 LCD_CLEAR \ 10- "LCD_Clear"
27419 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27420 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27421 CR ." I love you" \ display message on LCD
27422 ['] CR >BODY IS CR \ CR executes its default value
27423 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
27424 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27427 \ ------------------------------\
27429 \ ------------------------------\
27430 CODE START \ this routine replaces WARM and COLD default values by these of this application.
27431 \ ------------------------------\
27432 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
27433 0= IF \ if not done, customizes MARKER_DOES
27434 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
27435 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
27436 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
27437 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
27438 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27439 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
27440 MOV #RC5_INT,&IR_VEC \ init interrupt vector
27441 MOV #INI_R2L,PC \ then execute new INI_APP, without return
27445 \ ------------------------------\
27448 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
27450 MARKER {RC5TOLCD} \ restore the state before MARKER definition
27451 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
27452 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
27453 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
27454 \ {RC5TOLCD}+14: make room to save previous IR_VEC
27456 [UNDEFINED] CONSTANT [IF]
27457 \ https://forth-standard.org/standard/core/CONSTANT
27458 \ CONSTANT <name> n -- define a Forth CONSTANT
27462 MOV TOS,-2(W) \ PFA = n
27469 [UNDEFINED] STATE [IF]
27470 \ https://forth-standard.org/standard/core/STATE
27471 \ STATE -- a-addr holds compiler state
27472 STATEADR CONSTANT STATE
27476 \ https://forth-standard.org/standard/core/Equal
27477 \ = x1 x2 -- flag test x1=x2
27484 XOR #-1,TOS \ 1 flag Z = 1
27489 [UNDEFINED] IF [IF] \ define IF and THEN
27490 \ https://forth-standard.org/standard/core/IF
27491 \ IF -- IFadr initialize conditional forward branch
27492 CODE IF \ immediate
27495 MOV &DP,TOS \ -- HERE
27496 ADD #4,&DP \ compile one word, reserve one word
27497 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
27498 ADD #2,TOS \ -- HERE+2=IFadr
27502 \ https://forth-standard.org/standard/core/THEN
27503 \ THEN IFadr -- resolve forward branch
27504 CODE THEN \ immediate
27505 MOV &DP,0(TOS) \ -- IFadr
27511 [UNDEFINED] ELSE [IF]
27512 \ https://forth-standard.org/standard/core/ELSE
27513 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
27514 CODE ELSE \ immediate
27515 ADD #4,&DP \ make room to compile two words
27516 MOV &DP,W \ W=HERE+4
27518 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
27520 MOV W,TOS \ -- ELSEadr
27525 [UNDEFINED] IS [IF] \ define DEFER! and IS
27527 \ https://forth-standard.org/standard/core/DEFERStore
27528 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
27529 CODE DEFER! \ xt2 xt1 --
27530 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
27535 \ https://forth-standard.org/standard/core/IS
27538 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
27539 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
27540 \ or in a definition : ... ['] U. IS DISPLAY ...
27541 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
27543 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
27547 IF POSTPONE ['] POSTPONE DEFER!
27553 [UNDEFINED] >BODY [IF]
27554 \ https://forth-standard.org/standard/core/toBODY
27555 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
27562 \ CODE 20uS \ n -- 8MHz version
27563 \ BEGIN \ 4 + 16 ~ loop
27564 \ MOV #39,rDOCON \ 39
27571 \ MOV #XDOCON,rDOCON \ 2
27576 CODE 20_US \ n -- n * 20 us
27577 BEGIN \ here we presume that LCD_TIM_IFG = 1...
27579 BIT #1,&LCD_TIM_CTL \ 3
27580 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
27581 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
27583 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
27588 CODE TOP_LCD \ LCD Sample
27589 \ \ if write : %xxxx_WWWW --
27590 \ \ if read : -- %0000_RRRR
27591 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27592 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27593 0= IF \ write LCD bits pattern
27594 AND.B #LCD_DB,TOS \
27595 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27596 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27599 THEN \ read LCD bits pattern
27602 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27603 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27604 AND.B #LCD_DB,TOS \
27608 CODE LCD_WRC \ char -- Write Char
27609 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27611 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
27612 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
27613 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27614 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27615 COLON \ high level word starts here
27616 TOP_LCD 2 20_US \ write high nibble first
27620 CODE LCD_WRF \ func -- Write Fonction
27621 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27625 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
27626 : LCD_HOME $02 LCD_WRF 100 20_us ;
27628 \ [UNDEFINED] OR [IF]
27630 \ \ https://forth-standard.org/standard/core/OR
27631 \ \ C OR x1 x2 -- x3 logical OR
27639 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
27640 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
27641 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
27642 \ : LCD_FN_SET $20 OR LCD_WrF ;
27643 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
27644 \ : LCD_GOTO $80 OR LCD_WrF ;
27647 \ CODE LCD_RDS \ -- status Read Status
27648 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27649 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27650 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27651 \ COLON \ starts a FORTH word
27652 \ TOP_LCD 2 20_us \ -- %0000_HHHH
27653 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
27654 \ HI2LO \ switch from FORTH to assembler
27655 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
27656 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
27657 \ MOV @RSP+,IP \ restore IP saved by COLON
27661 \ CODE LCD_RDC \ -- char Read Char
27662 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27667 \ ******************************\
27668 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27669 \ ******************************\
27670 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
27671 BIT.B #SW2,&SW2_IN \ test switch S2
27672 0= IF \ case of switch S2 pressed
27673 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27675 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
27678 BIT.B #SW1,&SW1_IN \ test switch S1 input
27679 0= IF \ case of Switch S1 pressed
27680 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27682 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27689 \ ******************************\
27690 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
27691 \ ******************************\
27692 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27693 \ ******************************\
27694 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27695 \ \ SMclock = 8|16|24 MHz
27696 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27697 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27698 \ \ SR(9)=new Toggle bit memory (ADD on)
27699 \ ******************************\
27700 \ RC5_FirstStartBitHalfCycle: \
27701 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27702 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
27703 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
27705 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
27706 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
27708 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
27709 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
27711 MOV #1778,X \ RC5_Period * 1us
27712 MOV #14,W \ count of loop
27714 \ ******************************\
27715 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
27716 \ ******************************\ |
27717 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27718 \ RC5_Compute_3/4_Period: \ |
27719 RRUM #1,X \ X=1/2 cycle |
27722 ADD X,Y \ Y=3/4 cycle
27723 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
27725 \ ******************************\
27726 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27727 \ ******************************\
27728 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27729 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
27730 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27731 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27732 SUB #1,W \ decrement count loop
27733 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
27734 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27735 0<> WHILE \ ----> out of loop ----+
27736 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27738 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
27739 CMP Y,X \ 1 | cycle time out of bound ?
27740 U>= IF \ 2 ^ | yes:
27741 BIC #$30,&RC5_TIM_CTL \ | | stop timer
27742 GOTO FW1 \ | | quit on truncated RC5 message
27744 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
27746 REPEAT \ ----> loop back --+ | with X = new RC5_period value
27747 \ ******************************\ |
27748 \ RC5_SampleEndOf: \ <---------------------+
27749 \ ******************************\
27750 BIC #$30,&RC5_TIM_CTL \ stop timer
27751 \ ******************************\
27752 \ RC5_ComputeNewRC5word \
27753 \ ******************************\
27754 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
27755 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27756 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27757 \ ******************************\
27758 \ RC5_ComputeC6bit \
27759 \ ******************************\
27760 BIT #BIT14,T \ test /C6 bit in T
27761 0= IF BIS #BIT6,X \ set C6 bit in X
27762 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27763 \ ******************************\
27764 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27765 \ ******************************\
27766 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
27767 \ ******************************\
27768 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27769 XOR @RSP,T \ (new XOR old) Toggle bits
27770 BIT #UF10,T \ repeated RC5_command ?
27771 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
27772 XOR #UF10,0(RSP) \ 5 toggle bit memory
27773 \ ******************************\
27774 \ Display IR_RC5 code \
27775 \ ******************************\
27776 SUB #8,PSP \ TOS -- x x x x TOS
27777 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27778 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27779 MOV #$10,&BASEADR \ set hexadecimal base
27780 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27781 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27782 LO2HI \ switch from assembler to FORTH
27783 LCD_CLEAR \ set LCD cursor at home
27784 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27785 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27786 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27787 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27788 HI2LO \ -- switch from FORTH to assembler
27789 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27790 MOV @PSP+,TOS \ -- TOS
27792 MOV @RSP+,SR \ restore SR flags
27793 BIC #%1111_1000,SR \ but force CPU Active Mode
27794 RET \ (instead of RETI)
27798 \ ------------------------------\
27799 HDNCODE STOP_R2L \ define new STOP_APP
27800 \ ------------------------------\
27801 CMP #RET_ADR,&{RC5TOLCD}+8 \
27802 0<> IF \ if previous START executing
27803 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
27804 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
27805 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
27806 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
27807 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
27808 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
27809 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
27810 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
27811 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
27812 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
27817 \ ------------------------------\
27819 \ ------------------------------\
27820 BW1 \ <-- INI_R2L for some events
27822 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
27824 ." RC5toLCD is removed,"
27825 ." type START to restart"
27828 \ ------------------------------\
27830 \ ------------------------------\
27831 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
27832 \ ------------------------------\
27834 \ ------------------------------\
27835 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
27836 \ ------------------------------\
27837 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
27838 \ ------------------------------\
27839 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
27840 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
27842 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
27843 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
27845 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
27846 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
27847 \ CMP #4,TOS \ hardware RST
27848 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
27849 \ CMP #2,TOS \ Power_ON event
27850 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
27852 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
27854 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
27856 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
27857 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
27858 \ ------------------------------\
27859 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
27860 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27861 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27862 \ -- \ID input divider \ 10 = /4
27863 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27864 \ - \TBCLR TimerB Clear
27867 \ -------------------------------\
27868 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27869 \ -- \CM Capture Mode
27874 \ --- \OUTMOD \ 011 = set/reset
27880 \ -------------------------------\
27882 \ -------------------------------\
27884 \ ------------------------------\
27885 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27886 \ ------------------------------\
27887 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27888 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27889 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
27890 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27892 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
27893 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27895 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
27896 \ ------------------------------\
27897 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27898 \ ------------------------------\
27899 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
27900 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27901 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27902 \ ------------------------------\
27903 BIS.B #LCDVo,&LCDVo_DIR \
27904 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
27905 \ ------------------------------\
27906 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27907 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27908 \ ------------------------------\
27909 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27910 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27911 \ ******************************\
27913 \ ******************************\
27914 BIS.B #RC5,&IR_IE \ enable RC5_Int
27915 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27916 \ ******************************\
27917 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27918 \ ******************************\
27919 \ %01 0001 0100 \ TAxCTL
27920 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
27921 \ -- \ ID divided by 1
27922 \ -- \ MC MODE = up to TAxCCRn
27923 \ - \ TACLR clear timer count
27926 \ ------------------------------\
27927 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
27928 \ ------------------------------\
27930 \ --- \ TAIDEX pre divisor
27931 \ ------------------------------\
27932 \ %0000 0000 0000 0101 \ TAxCCR0
27933 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27934 \ ------------------------------\
27935 \ %0000 0000 0001 0000 \ TAxCCTL0
27936 \ - \ CAP capture/compare mode = compare
27939 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
27940 \ ------------------------------\
27941 \ define LPM mode for ACCEPT \
27942 \ ------------------------------\
27943 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
27944 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27945 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27946 \ ------------------------------\
27948 \ ------------------------------\
27950 \ ------------------------------\
27951 #1000 20_US \ 1- wait 20 ms
27952 %011 TOP_LCD \ 2- send DB5=DB4=1
27953 #205 20_US \ 3- wait 4,1 ms
27954 %011 TOP_LCD \ 4- send again DB5=DB4=1
27955 #5 20_US \ 5- wait 0,1 ms
27956 %011 TOP_LCD \ 6- send again again DB5=DB4=1
27957 #2 20_US \ wait 40 us = LCD cycle
27958 %010 TOP_LCD \ 7- send DB5=1 DB4=0
27959 #2 20_US \ wait 40 us = LCD cycle
27960 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27961 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27962 LCD_CLEAR \ 10- "LCD_Clear"
27963 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27964 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27965 LCD_CLEAR \ 10- "LCD_Clear"
27966 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27967 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27968 CR ." I love you" \ display message on LCD
27969 ['] CR >BODY IS CR \ CR executes its default value
27970 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
27971 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27974 \ ------------------------------\
27976 \ ------------------------------\
27977 CODE START \ this routine replaces WARM and COLD default values by these of this application.
27978 \ ------------------------------\
27979 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
27980 0= IF \ if not done, customizes MARKER_DOES
27981 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
27982 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
27983 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
27984 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
27985 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27986 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
27987 MOV #RC5_INT,&IR_VEC \ init interrupt vector
27988 MOV #INI_R2L,PC \ then execute new INI_APP, without return
27992 \ ------------------------------\
27995 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
27997 MARKER {RC5TOLCD} \ restore the state before MARKER definition
27998 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
27999 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
28000 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
28001 \ {RC5TOLCD}+14: make room to save previous IR_VEC
28003 [UNDEFINED] CONSTANT [IF]
28004 \ https://forth-standard.org/standard/core/CONSTANT
28005 \ CONSTANT <name> n -- define a Forth CONSTANT
28009 MOV TOS,-2(W) \ PFA = n
28016 [UNDEFINED] STATE [IF]
28017 \ https://forth-standard.org/standard/core/STATE
28018 \ STATE -- a-addr holds compiler state
28019 STATEADR CONSTANT STATE
28023 \ https://forth-standard.org/standard/core/Equal
28024 \ = x1 x2 -- flag test x1=x2
28031 XOR #-1,TOS \ 1 flag Z = 1
28036 [UNDEFINED] IF [IF] \ define IF and THEN
28037 \ https://forth-standard.org/standard/core/IF
28038 \ IF -- IFadr initialize conditional forward branch
28039 CODE IF \ immediate
28042 MOV &DP,TOS \ -- HERE
28043 ADD #4,&DP \ compile one word, reserve one word
28044 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
28045 ADD #2,TOS \ -- HERE+2=IFadr
28049 \ https://forth-standard.org/standard/core/THEN
28050 \ THEN IFadr -- resolve forward branch
28051 CODE THEN \ immediate
28052 MOV &DP,0(TOS) \ -- IFadr
28058 [UNDEFINED] ELSE [IF]
28059 \ https://forth-standard.org/standard/core/ELSE
28060 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
28061 CODE ELSE \ immediate
28062 ADD #4,&DP \ make room to compile two words
28063 MOV &DP,W \ W=HERE+4
28065 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
28067 MOV W,TOS \ -- ELSEadr
28072 [UNDEFINED] IS [IF] \ define DEFER! and IS
28074 \ https://forth-standard.org/standard/core/DEFERStore
28075 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
28076 CODE DEFER! \ xt2 xt1 --
28077 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
28082 \ https://forth-standard.org/standard/core/IS
28085 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
28086 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
28087 \ or in a definition : ... ['] U. IS DISPLAY ...
28088 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
28090 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
28094 IF POSTPONE ['] POSTPONE DEFER!
28100 [UNDEFINED] >BODY [IF]
28101 \ https://forth-standard.org/standard/core/toBODY
28102 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
28109 \ CODE 20uS \ n -- 8MHz version
28110 \ BEGIN \ 4 + 16 ~ loop
28111 \ MOV #39,rDOCON \ 39
28118 \ MOV #XDOCON,rDOCON \ 2
28123 CODE 20_US \ n -- n * 20 us
28124 BEGIN \ here we presume that LCD_TIM_IFG = 1...
28126 BIT #1,&LCD_TIM_CTL \ 3
28127 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
28128 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
28130 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
28135 CODE TOP_LCD \ LCD Sample
28136 \ \ if write : %xxxx_WWWW --
28137 \ \ if read : -- %0000_RRRR
28138 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28139 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28140 0= IF \ write LCD bits pattern
28141 AND.B #LCD_DB,TOS \
28142 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28143 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28146 THEN \ read LCD bits pattern
28149 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28150 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28151 AND.B #LCD_DB,TOS \
28155 CODE LCD_WRC \ char -- Write Char
28156 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28158 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
28159 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
28160 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28161 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28162 COLON \ high level word starts here
28163 TOP_LCD 2 20_US \ write high nibble first
28167 CODE LCD_WRF \ func -- Write Fonction
28168 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28172 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
28173 : LCD_HOME $02 LCD_WRF 100 20_us ;
28175 \ [UNDEFINED] OR [IF]
28177 \ \ https://forth-standard.org/standard/core/OR
28178 \ \ C OR x1 x2 -- x3 logical OR
28186 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
28187 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
28188 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
28189 \ : LCD_FN_SET $20 OR LCD_WrF ;
28190 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
28191 \ : LCD_GOTO $80 OR LCD_WrF ;
28194 \ CODE LCD_RDS \ -- status Read Status
28195 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28196 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28197 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28198 \ COLON \ starts a FORTH word
28199 \ TOP_LCD 2 20_us \ -- %0000_HHHH
28200 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
28201 \ HI2LO \ switch from FORTH to assembler
28202 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
28203 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
28204 \ MOV @RSP+,IP \ restore IP saved by COLON
28208 \ CODE LCD_RDC \ -- char Read Char
28209 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28214 \ ******************************\
28215 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28216 \ ******************************\
28217 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
28218 BIT.B #SW2,&SW2_IN \ test switch S2
28219 0= IF \ case of switch S2 pressed
28220 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28222 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
28225 BIT.B #SW1,&SW1_IN \ test switch S1 input
28226 0= IF \ case of Switch S1 pressed
28227 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28229 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28236 \ ******************************\
28237 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
28238 \ ******************************\
28239 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28240 \ ******************************\
28241 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28242 \ \ SMclock = 8|16|24 MHz
28243 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28244 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28245 \ \ SR(9)=new Toggle bit memory (ADD on)
28246 \ ******************************\
28247 \ RC5_FirstStartBitHalfCycle: \
28248 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28249 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
28250 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
28252 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
28253 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
28255 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
28256 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
28258 MOV #1778,X \ RC5_Period * 1us
28259 MOV #14,W \ count of loop
28261 \ ******************************\
28262 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
28263 \ ******************************\ |
28264 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28265 \ RC5_Compute_3/4_Period: \ |
28266 RRUM #1,X \ X=1/2 cycle |
28269 ADD X,Y \ Y=3/4 cycle
28270 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
28272 \ ******************************\
28273 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28274 \ ******************************\
28275 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28276 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
28277 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28278 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28279 SUB #1,W \ decrement count loop
28280 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
28281 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28282 0<> WHILE \ ----> out of loop ----+
28283 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28285 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
28286 CMP Y,X \ 1 | cycle time out of bound ?
28287 U>= IF \ 2 ^ | yes:
28288 BIC #$30,&RC5_TIM_CTL \ | | stop timer
28289 GOTO FW1 \ | | quit on truncated RC5 message
28291 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
28293 REPEAT \ ----> loop back --+ | with X = new RC5_period value
28294 \ ******************************\ |
28295 \ RC5_SampleEndOf: \ <---------------------+
28296 \ ******************************\
28297 BIC #$30,&RC5_TIM_CTL \ stop timer
28298 \ ******************************\
28299 \ RC5_ComputeNewRC5word \
28300 \ ******************************\
28301 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
28302 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
28303 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
28304 \ ******************************\
28305 \ RC5_ComputeC6bit \
28306 \ ******************************\
28307 BIT #BIT14,T \ test /C6 bit in T
28308 0= IF BIS #BIT6,X \ set C6 bit in X
28309 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
28310 \ ******************************\
28311 \ RC5_CommandByteIsDone \ -- BASE RC5_code
28312 \ ******************************\
28313 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
28314 \ ******************************\
28315 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
28316 XOR @RSP,T \ (new XOR old) Toggle bits
28317 BIT #UF10,T \ repeated RC5_command ?
28318 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
28319 XOR #UF10,0(RSP) \ 5 toggle bit memory
28320 \ ******************************\
28321 \ Display IR_RC5 code \
28322 \ ******************************\
28323 SUB #8,PSP \ TOS -- x x x x TOS
28324 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
28325 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
28326 MOV #$10,&BASEADR \ set hexadecimal base
28327 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
28328 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
28329 LO2HI \ switch from assembler to FORTH
28330 LCD_CLEAR \ set LCD cursor at home
28331 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
28332 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
28333 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
28334 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
28335 HI2LO \ -- switch from FORTH to assembler
28336 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
28337 MOV @PSP+,TOS \ -- TOS
28339 MOV @RSP+,SR \ restore SR flags
28340 BIC #%1111_1000,SR \ but force CPU Active Mode
28341 RET \ (instead of RETI)
28345 \ ------------------------------\
28346 HDNCODE STOP_R2L \ define new STOP_APP
28347 \ ------------------------------\
28348 CMP #RET_ADR,&{RC5TOLCD}+8 \
28349 0<> IF \ if previous START executing
28350 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
28351 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
28352 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
28353 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
28354 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
28355 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
28356 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
28357 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
28358 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
28359 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
28364 \ ------------------------------\
28366 \ ------------------------------\
28367 BW1 \ <-- INI_R2L for some events
28369 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28371 ." RC5toLCD is removed,"
28372 ." type START to restart"
28375 \ ------------------------------\
28377 \ ------------------------------\
28378 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
28379 \ ------------------------------\
28381 \ ------------------------------\
28382 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
28383 \ ------------------------------\
28384 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
28385 \ ------------------------------\
28386 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
28387 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
28389 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
28390 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
28392 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
28393 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
28394 \ CMP #4,TOS \ hardware RST
28395 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
28396 \ CMP #2,TOS \ Power_ON event
28397 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
28399 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
28401 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
28403 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
28404 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
28405 \ ------------------------------\
28406 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28407 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28408 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28409 \ -- \ID input divider \ 10 = /4
28410 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28411 \ - \TBCLR TimerB Clear
28414 \ -------------------------------\
28415 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28416 \ -- \CM Capture Mode
28421 \ --- \OUTMOD \ 011 = set/reset
28427 \ -------------------------------\
28429 \ -------------------------------\
28431 \ ------------------------------\
28432 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28433 \ ------------------------------\
28434 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28435 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28436 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28437 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28439 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28440 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28442 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28443 \ ------------------------------\
28444 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28445 \ ------------------------------\
28446 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28447 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28448 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28449 \ ------------------------------\
28450 BIS.B #LCDVo,&LCDVo_DIR \
28451 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28452 \ ------------------------------\
28453 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28454 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28455 \ ------------------------------\
28456 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28457 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28458 \ ******************************\
28460 \ ******************************\
28461 BIS.B #RC5,&IR_IE \ enable RC5_Int
28462 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28463 \ ******************************\
28464 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
28465 \ ******************************\
28466 \ %01 0001 0100 \ TAxCTL
28467 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
28468 \ -- \ ID divided by 1
28469 \ -- \ MC MODE = up to TAxCCRn
28470 \ - \ TACLR clear timer count
28473 \ ------------------------------\
28474 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
28475 \ ------------------------------\
28477 \ --- \ TAIDEX pre divisor
28478 \ ------------------------------\
28479 \ %0000 0000 0000 0101 \ TAxCCR0
28480 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
28481 \ ------------------------------\
28482 \ %0000 0000 0001 0000 \ TAxCCTL0
28483 \ - \ CAP capture/compare mode = compare
28486 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
28487 \ ------------------------------\
28488 \ define LPM mode for ACCEPT \
28489 \ ------------------------------\
28490 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
28491 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28492 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28493 \ ------------------------------\
28495 \ ------------------------------\
28497 \ ------------------------------\
28498 #1000 20_US \ 1- wait 20 ms
28499 %011 TOP_LCD \ 2- send DB5=DB4=1
28500 #205 20_US \ 3- wait 4,1 ms
28501 %011 TOP_LCD \ 4- send again DB5=DB4=1
28502 #5 20_US \ 5- wait 0,1 ms
28503 %011 TOP_LCD \ 6- send again again DB5=DB4=1
28504 #2 20_US \ wait 40 us = LCD cycle
28505 %010 TOP_LCD \ 7- send DB5=1 DB4=0
28506 #2 20_US \ wait 40 us = LCD cycle
28507 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28508 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28509 LCD_CLEAR \ 10- "LCD_Clear"
28510 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28511 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28512 LCD_CLEAR \ 10- "LCD_Clear"
28513 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28514 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28515 CR ." I love you" \ display message on LCD
28516 ['] CR >BODY IS CR \ CR executes its default value
28517 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
28518 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
28521 \ ------------------------------\
28523 \ ------------------------------\
28524 CODE START \ this routine replaces WARM and COLD default values by these of this application.
28525 \ ------------------------------\
28526 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
28527 0= IF \ if not done, customizes MARKER_DOES
28528 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
28529 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
28530 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
28531 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
28532 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
28533 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
28534 MOV #RC5_INT,&IR_VEC \ init interrupt vector
28535 MOV #INI_R2L,PC \ then execute new INI_APP, without return
28539 \ ------------------------------\
28542 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
28544 MARKER {RC5TOLCD} \ restore the state before MARKER definition
28545 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
28546 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
28547 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
28548 \ {RC5TOLCD}+14: make room to save previous IR_VEC
28550 [UNDEFINED] CONSTANT [IF]
28551 \ https://forth-standard.org/standard/core/CONSTANT
28552 \ CONSTANT <name> n -- define a Forth CONSTANT
28556 MOV TOS,-2(W) \ PFA = n
28563 [UNDEFINED] STATE [IF]
28564 \ https://forth-standard.org/standard/core/STATE
28565 \ STATE -- a-addr holds compiler state
28566 STATEADR CONSTANT STATE
28570 \ https://forth-standard.org/standard/core/Equal
28571 \ = x1 x2 -- flag test x1=x2
28578 XOR #-1,TOS \ 1 flag Z = 1
28583 [UNDEFINED] IF [IF] \ define IF and THEN
28584 \ https://forth-standard.org/standard/core/IF
28585 \ IF -- IFadr initialize conditional forward branch
28586 CODE IF \ immediate
28589 MOV &DP,TOS \ -- HERE
28590 ADD #4,&DP \ compile one word, reserve one word
28591 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
28592 ADD #2,TOS \ -- HERE+2=IFadr
28596 \ https://forth-standard.org/standard/core/THEN
28597 \ THEN IFadr -- resolve forward branch
28598 CODE THEN \ immediate
28599 MOV &DP,0(TOS) \ -- IFadr
28605 [UNDEFINED] ELSE [IF]
28606 \ https://forth-standard.org/standard/core/ELSE
28607 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
28608 CODE ELSE \ immediate
28609 ADD #4,&DP \ make room to compile two words
28610 MOV &DP,W \ W=HERE+4
28612 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
28614 MOV W,TOS \ -- ELSEadr
28619 [UNDEFINED] IS [IF] \ define DEFER! and IS
28621 \ https://forth-standard.org/standard/core/DEFERStore
28622 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
28623 CODE DEFER! \ xt2 xt1 --
28624 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
28629 \ https://forth-standard.org/standard/core/IS
28632 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
28633 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
28634 \ or in a definition : ... ['] U. IS DISPLAY ...
28635 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
28637 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
28641 IF POSTPONE ['] POSTPONE DEFER!
28647 [UNDEFINED] >BODY [IF]
28648 \ https://forth-standard.org/standard/core/toBODY
28649 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
28656 \ CODE 20uS \ n -- 8MHz version
28657 \ BEGIN \ 4 + 16 ~ loop
28658 \ MOV #39,rDOCON \ 39
28665 \ MOV #XDOCON,rDOCON \ 2
28670 CODE 20_US \ n -- n * 20 us
28671 BEGIN \ here we presume that LCD_TIM_IFG = 1...
28673 BIT #1,&LCD_TIM_CTL \ 3
28674 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
28675 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
28677 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
28682 CODE TOP_LCD \ LCD Sample
28683 \ \ if write : %xxxx_WWWW --
28684 \ \ if read : -- %0000_RRRR
28685 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28686 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28687 0= IF \ write LCD bits pattern
28688 AND.B #LCD_DB,TOS \
28689 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28690 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28693 THEN \ read LCD bits pattern
28696 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28697 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28698 AND.B #LCD_DB,TOS \
28702 CODE LCD_WRC \ char -- Write Char
28703 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28705 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
28706 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
28707 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28708 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28709 COLON \ high level word starts here
28710 TOP_LCD 2 20_US \ write high nibble first
28714 CODE LCD_WRF \ func -- Write Fonction
28715 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28719 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
28720 : LCD_HOME $02 LCD_WRF 100 20_us ;
28722 \ [UNDEFINED] OR [IF]
28724 \ \ https://forth-standard.org/standard/core/OR
28725 \ \ C OR x1 x2 -- x3 logical OR
28733 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
28734 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
28735 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
28736 \ : LCD_FN_SET $20 OR LCD_WrF ;
28737 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
28738 \ : LCD_GOTO $80 OR LCD_WrF ;
28741 \ CODE LCD_RDS \ -- status Read Status
28742 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28743 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28744 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28745 \ COLON \ starts a FORTH word
28746 \ TOP_LCD 2 20_us \ -- %0000_HHHH
28747 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
28748 \ HI2LO \ switch from FORTH to assembler
28749 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
28750 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
28751 \ MOV @RSP+,IP \ restore IP saved by COLON
28755 \ CODE LCD_RDC \ -- char Read Char
28756 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28761 \ ******************************\
28762 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28763 \ ******************************\
28764 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
28765 BIT.B #SW2,&SW2_IN \ test switch S2
28766 0= IF \ case of switch S2 pressed
28767 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28769 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
28772 BIT.B #SW1,&SW1_IN \ test switch S1 input
28773 0= IF \ case of Switch S1 pressed
28774 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28776 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28783 \ ******************************\
28784 HDNCODE 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 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
28797 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
28799 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
28800 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
28802 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
28803 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
28805 MOV #1778,X \ RC5_Period * 1us
28806 MOV #14,W \ count of loop
28808 \ ******************************\
28809 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
28810 \ ******************************\ |
28811 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28812 \ RC5_Compute_3/4_Period: \ |
28813 RRUM #1,X \ X=1/2 cycle |
28816 ADD X,Y \ Y=3/4 cycle
28817 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
28819 \ ******************************\
28820 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28821 \ ******************************\
28822 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28823 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
28824 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28825 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28826 SUB #1,W \ decrement count loop
28827 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
28828 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28829 0<> WHILE \ ----> out of loop ----+
28830 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28832 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
28833 CMP Y,X \ 1 | cycle time out of bound ?
28834 U>= IF \ 2 ^ | yes:
28835 BIC #$30,&RC5_TIM_CTL \ | | stop timer
28836 GOTO FW1 \ | | quit on truncated RC5 message
28838 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
28840 REPEAT \ ----> loop back --+ | with X = new RC5_period value
28841 \ ******************************\ |
28842 \ RC5_SampleEndOf: \ <---------------------+
28843 \ ******************************\
28844 BIC #$30,&RC5_TIM_CTL \ stop timer
28845 \ ******************************\
28846 \ RC5_ComputeNewRC5word \
28847 \ ******************************\
28848 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
28849 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
28850 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
28851 \ ******************************\
28852 \ RC5_ComputeC6bit \
28853 \ ******************************\
28854 BIT #BIT14,T \ test /C6 bit in T
28855 0= IF BIS #BIT6,X \ set C6 bit in X
28856 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
28857 \ ******************************\
28858 \ RC5_CommandByteIsDone \ -- BASE RC5_code
28859 \ ******************************\
28860 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
28861 \ ******************************\
28862 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
28863 XOR @RSP,T \ (new XOR old) Toggle bits
28864 BIT #UF10,T \ repeated RC5_command ?
28865 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
28866 XOR #UF10,0(RSP) \ 5 toggle bit memory
28867 \ ******************************\
28868 \ Display IR_RC5 code \
28869 \ ******************************\
28870 SUB #8,PSP \ TOS -- x x x x TOS
28871 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
28872 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
28873 MOV #$10,&BASEADR \ set hexadecimal base
28874 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
28875 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
28876 LO2HI \ switch from assembler to FORTH
28877 LCD_CLEAR \ set LCD cursor at home
28878 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
28879 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
28880 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
28881 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
28882 HI2LO \ -- switch from FORTH to assembler
28883 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
28884 MOV @PSP+,TOS \ -- TOS
28886 MOV @RSP+,SR \ restore SR flags
28887 BIC #%1111_1000,SR \ but force CPU Active Mode
28888 RET \ (instead of RETI)
28892 \ ------------------------------\
28893 HDNCODE STOP_R2L \ define new STOP_APP
28894 \ ------------------------------\
28895 CMP #RET_ADR,&{RC5TOLCD}+8 \
28896 0<> IF \ if previous START executing
28897 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
28898 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
28899 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
28900 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
28901 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
28902 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
28903 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
28904 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
28905 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
28906 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
28911 \ ------------------------------\
28913 \ ------------------------------\
28914 BW1 \ <-- INI_R2L for some events
28916 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28918 ." RC5toLCD is removed,"
28919 ." type START to restart"
28922 \ ------------------------------\
28924 \ ------------------------------\
28925 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
28926 \ ------------------------------\
28928 \ ------------------------------\
28929 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
28930 \ ------------------------------\
28931 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
28932 \ ------------------------------\
28933 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
28934 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
28936 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
28937 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
28939 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
28940 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
28941 \ CMP #4,TOS \ hardware RST
28942 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
28943 \ CMP #2,TOS \ Power_ON event
28944 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
28946 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
28948 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
28950 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
28951 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
28952 \ ------------------------------\
28953 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28954 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28955 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28956 \ -- \ID input divider \ 10 = /4
28957 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28958 \ - \TBCLR TimerB Clear
28961 \ -------------------------------\
28962 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28963 \ -- \CM Capture Mode
28968 \ --- \OUTMOD \ 011 = set/reset
28974 \ -------------------------------\
28976 \ -------------------------------\
28978 \ ------------------------------\
28979 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28980 \ ------------------------------\
28981 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28982 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28983 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28984 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28986 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28987 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28989 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28990 \ ------------------------------\
28991 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28992 \ ------------------------------\
28993 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28994 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28995 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28996 \ ------------------------------\
28997 BIS.B #LCDVo,&LCDVo_DIR \
28998 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28999 \ ------------------------------\
29000 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29001 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29002 \ ------------------------------\
29003 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29004 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29005 \ ******************************\
29007 \ ******************************\
29008 BIS.B #RC5,&IR_IE \ enable RC5_Int
29009 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29010 \ ******************************\
29011 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29012 \ ******************************\
29013 \ %01 0001 0100 \ TAxCTL
29014 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
29015 \ -- \ ID divided by 1
29016 \ -- \ MC MODE = up to TAxCCRn
29017 \ - \ TACLR clear timer count
29020 \ ------------------------------\
29021 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
29022 \ ------------------------------\
29024 \ --- \ TAIDEX pre divisor
29025 \ ------------------------------\
29026 \ %0000 0000 0000 0101 \ TAxCCR0
29027 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29028 \ ------------------------------\
29029 \ %0000 0000 0001 0000 \ TAxCCTL0
29030 \ - \ CAP capture/compare mode = compare
29033 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
29034 \ ------------------------------\
29035 \ define LPM mode for ACCEPT \
29036 \ ------------------------------\
29037 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
29038 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29039 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29040 \ ------------------------------\
29042 \ ------------------------------\
29044 \ ------------------------------\
29045 #1000 20_US \ 1- wait 20 ms
29046 %011 TOP_LCD \ 2- send DB5=DB4=1
29047 #205 20_US \ 3- wait 4,1 ms
29048 %011 TOP_LCD \ 4- send again DB5=DB4=1
29049 #5 20_US \ 5- wait 0,1 ms
29050 %011 TOP_LCD \ 6- send again again DB5=DB4=1
29051 #2 20_US \ wait 40 us = LCD cycle
29052 %010 TOP_LCD \ 7- send DB5=1 DB4=0
29053 #2 20_US \ wait 40 us = LCD cycle
29054 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29055 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29056 LCD_CLEAR \ 10- "LCD_Clear"
29057 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29058 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29059 LCD_CLEAR \ 10- "LCD_Clear"
29060 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29061 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29062 CR ." I love you" \ display message on LCD
29063 ['] CR >BODY IS CR \ CR executes its default value
29064 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
29065 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29068 \ ------------------------------\
29070 \ ------------------------------\
29071 CODE START \ this routine replaces WARM and COLD default values by these of this application.
29072 \ ------------------------------\
29073 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
29074 0= IF \ if not done, customizes MARKER_DOES
29075 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
29076 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
29077 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
29078 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
29079 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29080 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
29081 MOV #RC5_INT,&IR_VEC \ init interrupt vector
29082 MOV #INI_R2L,PC \ then execute new INI_APP, without return
29086 \ ------------------------------\
29089 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29091 MARKER {RC5TOLCD} \ restore the state before MARKER definition
29092 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
29093 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
29094 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
29095 \ {RC5TOLCD}+14: make room to save previous IR_VEC
29097 [UNDEFINED] CONSTANT [IF]
29098 \ https://forth-standard.org/standard/core/CONSTANT
29099 \ CONSTANT <name> n -- define a Forth CONSTANT
29103 MOV TOS,-2(W) \ PFA = n
29110 [UNDEFINED] STATE [IF]
29111 \ https://forth-standard.org/standard/core/STATE
29112 \ STATE -- a-addr holds compiler state
29113 STATEADR CONSTANT STATE
29117 \ https://forth-standard.org/standard/core/Equal
29118 \ = x1 x2 -- flag test x1=x2
29125 XOR #-1,TOS \ 1 flag Z = 1
29130 [UNDEFINED] IF [IF] \ define IF and THEN
29131 \ https://forth-standard.org/standard/core/IF
29132 \ IF -- IFadr initialize conditional forward branch
29133 CODE IF \ immediate
29136 MOV &DP,TOS \ -- HERE
29137 ADD #4,&DP \ compile one word, reserve one word
29138 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
29139 ADD #2,TOS \ -- HERE+2=IFadr
29143 \ https://forth-standard.org/standard/core/THEN
29144 \ THEN IFadr -- resolve forward branch
29145 CODE THEN \ immediate
29146 MOV &DP,0(TOS) \ -- IFadr
29152 [UNDEFINED] ELSE [IF]
29153 \ https://forth-standard.org/standard/core/ELSE
29154 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
29155 CODE ELSE \ immediate
29156 ADD #4,&DP \ make room to compile two words
29157 MOV &DP,W \ W=HERE+4
29159 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
29161 MOV W,TOS \ -- ELSEadr
29166 [UNDEFINED] IS [IF] \ define DEFER! and IS
29168 \ https://forth-standard.org/standard/core/DEFERStore
29169 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
29170 CODE DEFER! \ xt2 xt1 --
29171 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
29176 \ https://forth-standard.org/standard/core/IS
29179 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
29180 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
29181 \ or in a definition : ... ['] U. IS DISPLAY ...
29182 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
29184 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
29188 IF POSTPONE ['] POSTPONE DEFER!
29194 [UNDEFINED] >BODY [IF]
29195 \ https://forth-standard.org/standard/core/toBODY
29196 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
29203 \ CODE 20uS \ n -- 8MHz version
29204 \ BEGIN \ 4 + 16 ~ loop
29205 \ MOV #39,rDOCON \ 39
29212 \ MOV #XDOCON,rDOCON \ 2
29217 CODE 20_US \ n -- n * 20 us
29218 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29220 BIT #1,&LCD_TIM_CTL \ 3
29221 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29222 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29224 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29229 CODE TOP_LCD \ LCD Sample
29230 \ \ if write : %xxxx_WWWW --
29231 \ \ if read : -- %0000_RRRR
29232 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29233 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29234 0= IF \ write LCD bits pattern
29235 AND.B #LCD_DB,TOS \
29236 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29237 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29240 THEN \ read LCD bits pattern
29243 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29244 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29245 AND.B #LCD_DB,TOS \
29249 CODE LCD_WRC \ char -- Write Char
29250 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29252 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
29253 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
29254 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29255 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29256 COLON \ high level word starts here
29257 TOP_LCD 2 20_US \ write high nibble first
29261 CODE LCD_WRF \ func -- Write Fonction
29262 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29266 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29267 : LCD_HOME $02 LCD_WRF 100 20_us ;
29269 \ [UNDEFINED] OR [IF]
29271 \ \ https://forth-standard.org/standard/core/OR
29272 \ \ C OR x1 x2 -- x3 logical OR
29280 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29281 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29282 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29283 \ : LCD_FN_SET $20 OR LCD_WrF ;
29284 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29285 \ : LCD_GOTO $80 OR LCD_WrF ;
29288 \ CODE LCD_RDS \ -- status Read Status
29289 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29290 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29291 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29292 \ COLON \ starts a FORTH word
29293 \ TOP_LCD 2 20_us \ -- %0000_HHHH
29294 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
29295 \ HI2LO \ switch from FORTH to assembler
29296 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
29297 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
29298 \ MOV @RSP+,IP \ restore IP saved by COLON
29302 \ CODE LCD_RDC \ -- char Read Char
29303 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29308 \ ******************************\
29309 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29310 \ ******************************\
29311 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29312 BIT.B #SW2,&SW2_IN \ test switch S2
29313 0= IF \ case of switch S2 pressed
29314 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29316 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
29319 BIT.B #SW1,&SW1_IN \ test switch S1 input
29320 0= IF \ case of Switch S1 pressed
29321 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29323 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29330 \ ******************************\
29331 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
29332 \ ******************************\
29333 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29334 \ ******************************\
29335 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29336 \ \ SMclock = 8|16|24 MHz
29337 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29338 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29339 \ \ SR(9)=new Toggle bit memory (ADD on)
29340 \ ******************************\
29341 \ RC5_FirstStartBitHalfCycle: \
29342 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29343 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
29344 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
29346 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
29347 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
29349 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
29350 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
29352 MOV #1778,X \ RC5_Period * 1us
29353 MOV #14,W \ count of loop
29355 \ ******************************\
29356 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
29357 \ ******************************\ |
29358 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29359 \ RC5_Compute_3/4_Period: \ |
29360 RRUM #1,X \ X=1/2 cycle |
29363 ADD X,Y \ Y=3/4 cycle
29364 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
29366 \ ******************************\
29367 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29368 \ ******************************\
29369 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29370 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
29371 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29372 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29373 SUB #1,W \ decrement count loop
29374 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
29375 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29376 0<> WHILE \ ----> out of loop ----+
29377 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29379 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
29380 CMP Y,X \ 1 | cycle time out of bound ?
29381 U>= IF \ 2 ^ | yes:
29382 BIC #$30,&RC5_TIM_CTL \ | | stop timer
29383 GOTO FW1 \ | | quit on truncated RC5 message
29385 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
29387 REPEAT \ ----> loop back --+ | with X = new RC5_period value
29388 \ ******************************\ |
29389 \ RC5_SampleEndOf: \ <---------------------+
29390 \ ******************************\
29391 BIC #$30,&RC5_TIM_CTL \ stop timer
29392 \ ******************************\
29393 \ RC5_ComputeNewRC5word \
29394 \ ******************************\
29395 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
29396 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
29397 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
29398 \ ******************************\
29399 \ RC5_ComputeC6bit \
29400 \ ******************************\
29401 BIT #BIT14,T \ test /C6 bit in T
29402 0= IF BIS #BIT6,X \ set C6 bit in X
29403 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
29404 \ ******************************\
29405 \ RC5_CommandByteIsDone \ -- BASE RC5_code
29406 \ ******************************\
29407 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
29408 \ ******************************\
29409 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
29410 XOR @RSP,T \ (new XOR old) Toggle bits
29411 BIT #UF10,T \ repeated RC5_command ?
29412 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
29413 XOR #UF10,0(RSP) \ 5 toggle bit memory
29414 \ ******************************\
29415 \ Display IR_RC5 code \
29416 \ ******************************\
29417 SUB #8,PSP \ TOS -- x x x x TOS
29418 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
29419 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
29420 MOV #$10,&BASEADR \ set hexadecimal base
29421 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
29422 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
29423 LO2HI \ switch from assembler to FORTH
29424 LCD_CLEAR \ set LCD cursor at home
29425 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
29426 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
29427 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
29428 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
29429 HI2LO \ -- switch from FORTH to assembler
29430 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
29431 MOV @PSP+,TOS \ -- TOS
29433 MOV @RSP+,SR \ restore SR flags
29434 BIC #%1111_1000,SR \ but force CPU Active Mode
29435 RET \ (instead of RETI)
29439 \ ------------------------------\
29440 HDNCODE STOP_R2L \ define new STOP_APP
29441 \ ------------------------------\
29442 CMP #RET_ADR,&{RC5TOLCD}+8 \
29443 0<> IF \ if previous START executing
29444 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
29445 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
29446 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
29447 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
29448 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
29449 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
29450 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
29451 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
29452 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
29453 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
29458 \ ------------------------------\
29460 \ ------------------------------\
29461 BW1 \ <-- INI_R2L for some events
29463 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
29465 ." RC5toLCD is removed,"
29466 ." type START to restart"
29469 \ ------------------------------\
29471 \ ------------------------------\
29472 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
29473 \ ------------------------------\
29475 \ ------------------------------\
29476 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
29477 \ ------------------------------\
29478 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
29479 \ ------------------------------\
29480 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
29481 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
29483 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
29484 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
29486 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
29487 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
29488 \ CMP #4,TOS \ hardware RST
29489 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
29490 \ CMP #2,TOS \ Power_ON event
29491 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
29493 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
29495 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
29497 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
29498 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
29499 \ ------------------------------\
29500 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
29501 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29502 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29503 \ -- \ID input divider \ 10 = /4
29504 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
29505 \ - \TBCLR TimerB Clear
29508 \ -------------------------------\
29509 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29510 \ -- \CM Capture Mode
29515 \ --- \OUTMOD \ 011 = set/reset
29521 \ -------------------------------\
29523 \ -------------------------------\
29525 \ ------------------------------\
29526 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
29527 \ ------------------------------\
29528 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
29529 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
29530 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
29531 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
29533 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
29534 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
29536 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
29537 \ ------------------------------\
29538 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
29539 \ ------------------------------\
29540 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
29541 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
29542 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29543 \ ------------------------------\
29544 BIS.B #LCDVo,&LCDVo_DIR \
29545 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
29546 \ ------------------------------\
29547 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29548 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29549 \ ------------------------------\
29550 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29551 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29552 \ ******************************\
29554 \ ******************************\
29555 BIS.B #RC5,&IR_IE \ enable RC5_Int
29556 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29557 \ ******************************\
29558 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29559 \ ******************************\
29560 \ %01 0001 0100 \ TAxCTL
29561 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
29562 \ -- \ ID divided by 1
29563 \ -- \ MC MODE = up to TAxCCRn
29564 \ - \ TACLR clear timer count
29567 \ ------------------------------\
29568 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
29569 \ ------------------------------\
29571 \ --- \ TAIDEX pre divisor
29572 \ ------------------------------\
29573 \ %0000 0000 0000 0101 \ TAxCCR0
29574 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29575 \ ------------------------------\
29576 \ %0000 0000 0001 0000 \ TAxCCTL0
29577 \ - \ CAP capture/compare mode = compare
29580 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
29581 \ ------------------------------\
29582 \ define LPM mode for ACCEPT \
29583 \ ------------------------------\
29584 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
29585 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29586 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29587 \ ------------------------------\
29589 \ ------------------------------\
29591 \ ------------------------------\
29592 #1000 20_US \ 1- wait 20 ms
29593 %011 TOP_LCD \ 2- send DB5=DB4=1
29594 #205 20_US \ 3- wait 4,1 ms
29595 %011 TOP_LCD \ 4- send again DB5=DB4=1
29596 #5 20_US \ 5- wait 0,1 ms
29597 %011 TOP_LCD \ 6- send again again DB5=DB4=1
29598 #2 20_US \ wait 40 us = LCD cycle
29599 %010 TOP_LCD \ 7- send DB5=1 DB4=0
29600 #2 20_US \ wait 40 us = LCD cycle
29601 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29602 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29603 LCD_CLEAR \ 10- "LCD_Clear"
29604 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29605 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29606 LCD_CLEAR \ 10- "LCD_Clear"
29607 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29608 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29609 CR ." I love you" \ display message on LCD
29610 ['] CR >BODY IS CR \ CR executes its default value
29611 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
29612 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29615 \ ------------------------------\
29617 \ ------------------------------\
29618 CODE START \ this routine replaces WARM and COLD default values by these of this application.
29619 \ ------------------------------\
29620 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
29621 0= IF \ if not done, customizes MARKER_DOES
29622 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
29623 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
29624 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
29625 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
29626 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29627 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
29628 MOV #RC5_INT,&IR_VEC \ init interrupt vector
29629 MOV #INI_R2L,PC \ then execute new INI_APP, without return
29633 \ ------------------------------\
29636 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29638 MARKER {RC5TOLCD} \ restore the state before MARKER definition
29639 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
29640 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
29641 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
29642 \ {RC5TOLCD}+14: make room to save previous IR_VEC
29644 [UNDEFINED] CONSTANT [IF]
29645 \ https://forth-standard.org/standard/core/CONSTANT
29646 \ CONSTANT <name> n -- define a Forth CONSTANT
29650 MOV TOS,-2(W) \ PFA = n
29657 [UNDEFINED] STATE [IF]
29658 \ https://forth-standard.org/standard/core/STATE
29659 \ STATE -- a-addr holds compiler state
29660 STATEADR CONSTANT STATE
29664 \ https://forth-standard.org/standard/core/Equal
29665 \ = x1 x2 -- flag test x1=x2
29672 XOR #-1,TOS \ 1 flag Z = 1
29677 [UNDEFINED] IF [IF] \ define IF and THEN
29678 \ https://forth-standard.org/standard/core/IF
29679 \ IF -- IFadr initialize conditional forward branch
29680 CODE IF \ immediate
29683 MOV &DP,TOS \ -- HERE
29684 ADD #4,&DP \ compile one word, reserve one word
29685 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
29686 ADD #2,TOS \ -- HERE+2=IFadr
29690 \ https://forth-standard.org/standard/core/THEN
29691 \ THEN IFadr -- resolve forward branch
29692 CODE THEN \ immediate
29693 MOV &DP,0(TOS) \ -- IFadr
29699 [UNDEFINED] ELSE [IF]
29700 \ https://forth-standard.org/standard/core/ELSE
29701 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
29702 CODE ELSE \ immediate
29703 ADD #4,&DP \ make room to compile two words
29704 MOV &DP,W \ W=HERE+4
29706 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
29708 MOV W,TOS \ -- ELSEadr
29713 [UNDEFINED] IS [IF] \ define DEFER! and IS
29715 \ https://forth-standard.org/standard/core/DEFERStore
29716 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
29717 CODE DEFER! \ xt2 xt1 --
29718 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
29723 \ https://forth-standard.org/standard/core/IS
29726 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
29727 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
29728 \ or in a definition : ... ['] U. IS DISPLAY ...
29729 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
29731 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
29735 IF POSTPONE ['] POSTPONE DEFER!
29741 [UNDEFINED] >BODY [IF]
29742 \ https://forth-standard.org/standard/core/toBODY
29743 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
29750 \ CODE 20uS \ n -- 8MHz version
29751 \ BEGIN \ 4 + 16 ~ loop
29752 \ MOV #39,rDOCON \ 39
29759 \ MOV #XDOCON,rDOCON \ 2
29764 CODE 20_US \ n -- n * 20 us
29765 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29767 BIT #1,&LCD_TIM_CTL \ 3
29768 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29769 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29771 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29776 CODE TOP_LCD \ LCD Sample
29777 \ \ if write : %xxxx_WWWW --
29778 \ \ if read : -- %0000_RRRR
29779 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29780 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29781 0= IF \ write LCD bits pattern
29782 AND.B #LCD_DB,TOS \
29783 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29784 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29787 THEN \ read LCD bits pattern
29790 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29791 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29792 AND.B #LCD_DB,TOS \
29796 CODE LCD_WRC \ char -- Write Char
29797 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29799 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
29800 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
29801 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29802 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29803 COLON \ high level word starts here
29804 TOP_LCD 2 20_US \ write high nibble first
29808 CODE LCD_WRF \ func -- Write Fonction
29809 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29813 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29814 : LCD_HOME $02 LCD_WRF 100 20_us ;
29816 \ [UNDEFINED] OR [IF]
29818 \ \ https://forth-standard.org/standard/core/OR
29819 \ \ C OR x1 x2 -- x3 logical OR
29827 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29828 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29829 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29830 \ : LCD_FN_SET $20 OR LCD_WrF ;
29831 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29832 \ : LCD_GOTO $80 OR LCD_WrF ;
29835 \ CODE LCD_RDS \ -- status Read Status
29836 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29837 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29838 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29839 \ COLON \ starts a FORTH word
29840 \ TOP_LCD 2 20_us \ -- %0000_HHHH
29841 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
29842 \ HI2LO \ switch from FORTH to assembler
29843 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
29844 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
29845 \ MOV @RSP+,IP \ restore IP saved by COLON
29849 \ CODE LCD_RDC \ -- char Read Char
29850 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29855 \ ******************************\
29856 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29857 \ ******************************\
29858 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29859 BIT.B #SW2,&SW2_IN \ test switch S2
29860 0= IF \ case of switch S2 pressed
29861 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29863 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
29866 BIT.B #SW1,&SW1_IN \ test switch S1 input
29867 0= IF \ case of Switch S1 pressed
29868 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29870 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29877 \ ******************************\
29878 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
29879 \ ******************************\
29880 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29881 \ ******************************\
29882 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29883 \ \ SMclock = 8|16|24 MHz
29884 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29885 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29886 \ \ SR(9)=new Toggle bit memory (ADD on)
29887 \ ******************************\
29888 \ RC5_FirstStartBitHalfCycle: \
29889 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29890 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
29891 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
29893 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
29894 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
29896 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
29897 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
29899 MOV #1778,X \ RC5_Period * 1us
29900 MOV #14,W \ count of loop
29902 \ ******************************\
29903 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
29904 \ ******************************\ |
29905 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29906 \ RC5_Compute_3/4_Period: \ |
29907 RRUM #1,X \ X=1/2 cycle |
29910 ADD X,Y \ Y=3/4 cycle
29911 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
29913 \ ******************************\
29914 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29915 \ ******************************\
29916 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29917 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
29918 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29919 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29920 SUB #1,W \ decrement count loop
29921 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
29922 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29923 0<> WHILE \ ----> out of loop ----+
29924 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29926 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
29927 CMP Y,X \ 1 | cycle time out of bound ?
29928 U>= IF \ 2 ^ | yes:
29929 BIC #$30,&RC5_TIM_CTL \ | | stop timer
29930 GOTO FW1 \ | | quit on truncated RC5 message
29932 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
29934 REPEAT \ ----> loop back --+ | with X = new RC5_period value
29935 \ ******************************\ |
29936 \ RC5_SampleEndOf: \ <---------------------+
29937 \ ******************************\
29938 BIC #$30,&RC5_TIM_CTL \ stop timer
29939 \ ******************************\
29940 \ RC5_ComputeNewRC5word \
29941 \ ******************************\
29942 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
29943 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
29944 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
29945 \ ******************************\
29946 \ RC5_ComputeC6bit \
29947 \ ******************************\
29948 BIT #BIT14,T \ test /C6 bit in T
29949 0= IF BIS #BIT6,X \ set C6 bit in X
29950 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
29951 \ ******************************\
29952 \ RC5_CommandByteIsDone \ -- BASE RC5_code
29953 \ ******************************\
29954 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
29955 \ ******************************\
29956 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
29957 XOR @RSP,T \ (new XOR old) Toggle bits
29958 BIT #UF10,T \ repeated RC5_command ?
29959 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
29960 XOR #UF10,0(RSP) \ 5 toggle bit memory
29961 \ ******************************\
29962 \ Display IR_RC5 code \
29963 \ ******************************\
29964 SUB #8,PSP \ TOS -- x x x x TOS
29965 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
29966 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
29967 MOV #$10,&BASEADR \ set hexadecimal base
29968 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
29969 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
29970 LO2HI \ switch from assembler to FORTH
29971 LCD_CLEAR \ set LCD cursor at home
29972 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
29973 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
29974 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
29975 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
29976 HI2LO \ -- switch from FORTH to assembler
29977 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
29978 MOV @PSP+,TOS \ -- TOS
29980 MOV @RSP+,SR \ restore SR flags
29981 BIC #%1111_1000,SR \ but force CPU Active Mode
29982 RET \ (instead of RETI)
29986 \ ------------------------------\
29987 HDNCODE STOP_R2L \ define new STOP_APP
29988 \ ------------------------------\
29989 CMP #RET_ADR,&{RC5TOLCD}+8 \
29990 0<> IF \ if previous START executing
29991 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
29992 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
29993 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
29994 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
29995 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
29996 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
29997 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
29998 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
29999 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
30000 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
30005 \ ------------------------------\
30007 \ ------------------------------\
30008 BW1 \ <-- INI_R2L for some events
30010 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30012 ." RC5toLCD is removed,"
30013 ." type START to restart"
30016 \ ------------------------------\
30018 \ ------------------------------\
30019 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
30020 \ ------------------------------\
30022 \ ------------------------------\
30023 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
30024 \ ------------------------------\
30025 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
30026 \ ------------------------------\
30027 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
30028 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
30030 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
30031 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
30033 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
30034 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
30035 \ CMP #4,TOS \ hardware RST
30036 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
30037 \ CMP #2,TOS \ Power_ON event
30038 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30040 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30042 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30044 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30045 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
30046 \ ------------------------------\
30047 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30048 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30049 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30050 \ -- \ID input divider \ 10 = /4
30051 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30052 \ - \TBCLR TimerB Clear
30055 \ -------------------------------\
30056 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30057 \ -- \CM Capture Mode
30062 \ --- \OUTMOD \ 011 = set/reset
30068 \ -------------------------------\
30070 \ -------------------------------\
30072 \ ------------------------------\
30073 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30074 \ ------------------------------\
30075 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30076 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30077 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30078 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30080 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30081 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30083 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30084 \ ------------------------------\
30085 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30086 \ ------------------------------\
30087 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30088 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30089 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30090 \ ------------------------------\
30091 BIS.B #LCDVo,&LCDVo_DIR \
30092 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30093 \ ------------------------------\
30094 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30095 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30096 \ ------------------------------\
30097 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30098 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30099 \ ******************************\
30101 \ ******************************\
30102 BIS.B #RC5,&IR_IE \ enable RC5_Int
30103 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30104 \ ******************************\
30105 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30106 \ ******************************\
30107 \ %01 0001 0100 \ TAxCTL
30108 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30109 \ -- \ ID divided by 1
30110 \ -- \ MC MODE = up to TAxCCRn
30111 \ - \ TACLR clear timer count
30114 \ ------------------------------\
30115 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30116 \ ------------------------------\
30118 \ --- \ TAIDEX pre divisor
30119 \ ------------------------------\
30120 \ %0000 0000 0000 0101 \ TAxCCR0
30121 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30122 \ ------------------------------\
30123 \ %0000 0000 0001 0000 \ TAxCCTL0
30124 \ - \ CAP capture/compare mode = compare
30127 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30128 \ ------------------------------\
30129 \ define LPM mode for ACCEPT \
30130 \ ------------------------------\
30131 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
30132 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30133 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30134 \ ------------------------------\
30136 \ ------------------------------\
30138 \ ------------------------------\
30139 #1000 20_US \ 1- wait 20 ms
30140 %011 TOP_LCD \ 2- send DB5=DB4=1
30141 #205 20_US \ 3- wait 4,1 ms
30142 %011 TOP_LCD \ 4- send again DB5=DB4=1
30143 #5 20_US \ 5- wait 0,1 ms
30144 %011 TOP_LCD \ 6- send again again DB5=DB4=1
30145 #2 20_US \ wait 40 us = LCD cycle
30146 %010 TOP_LCD \ 7- send DB5=1 DB4=0
30147 #2 20_US \ wait 40 us = LCD cycle
30148 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30149 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30150 LCD_CLEAR \ 10- "LCD_Clear"
30151 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30152 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30153 LCD_CLEAR \ 10- "LCD_Clear"
30154 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30155 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30156 CR ." I love you" \ display message on LCD
30157 ['] CR >BODY IS CR \ CR executes its default value
30158 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
30159 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30162 \ ------------------------------\
30164 \ ------------------------------\
30165 CODE START \ this routine replaces WARM and COLD default values by these of this application.
30166 \ ------------------------------\
30167 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
30168 0= IF \ if not done, customizes MARKER_DOES
30169 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
30170 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
30171 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
30172 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
30173 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30174 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
30175 MOV #RC5_INT,&IR_VEC \ init interrupt vector
30176 MOV #INI_R2L,PC \ then execute new INI_APP, without return
30180 \ ------------------------------\
30183 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
30185 MARKER {RC5TOLCD} \ restore the state before MARKER definition
30186 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
30187 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
30188 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
30189 \ {RC5TOLCD}+14: make room to save previous IR_VEC
30191 [UNDEFINED] CONSTANT [IF]
30192 \ https://forth-standard.org/standard/core/CONSTANT
30193 \ CONSTANT <name> n -- define a Forth CONSTANT
30197 MOV TOS,-2(W) \ PFA = n
30204 [UNDEFINED] STATE [IF]
30205 \ https://forth-standard.org/standard/core/STATE
30206 \ STATE -- a-addr holds compiler state
30207 STATEADR CONSTANT STATE
30211 \ https://forth-standard.org/standard/core/Equal
30212 \ = x1 x2 -- flag test x1=x2
30219 XOR #-1,TOS \ 1 flag Z = 1
30224 [UNDEFINED] IF [IF] \ define IF and THEN
30225 \ https://forth-standard.org/standard/core/IF
30226 \ IF -- IFadr initialize conditional forward branch
30227 CODE IF \ immediate
30230 MOV &DP,TOS \ -- HERE
30231 ADD #4,&DP \ compile one word, reserve one word
30232 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
30233 ADD #2,TOS \ -- HERE+2=IFadr
30237 \ https://forth-standard.org/standard/core/THEN
30238 \ THEN IFadr -- resolve forward branch
30239 CODE THEN \ immediate
30240 MOV &DP,0(TOS) \ -- IFadr
30246 [UNDEFINED] ELSE [IF]
30247 \ https://forth-standard.org/standard/core/ELSE
30248 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
30249 CODE ELSE \ immediate
30250 ADD #4,&DP \ make room to compile two words
30251 MOV &DP,W \ W=HERE+4
30253 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
30255 MOV W,TOS \ -- ELSEadr
30260 [UNDEFINED] IS [IF] \ define DEFER! and IS
30262 \ https://forth-standard.org/standard/core/DEFERStore
30263 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
30264 CODE DEFER! \ xt2 xt1 --
30265 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
30270 \ https://forth-standard.org/standard/core/IS
30273 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
30274 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
30275 \ or in a definition : ... ['] U. IS DISPLAY ...
30276 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
30278 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
30282 IF POSTPONE ['] POSTPONE DEFER!
30288 [UNDEFINED] >BODY [IF]
30289 \ https://forth-standard.org/standard/core/toBODY
30290 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
30297 \ CODE 20uS \ n -- 8MHz version
30298 \ BEGIN \ 4 + 16 ~ loop
30299 \ MOV #39,rDOCON \ 39
30306 \ MOV #XDOCON,rDOCON \ 2
30311 CODE 20_US \ n -- n * 20 us
30312 BEGIN \ here we presume that LCD_TIM_IFG = 1...
30314 BIT #1,&LCD_TIM_CTL \ 3
30315 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
30316 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
30318 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
30323 CODE TOP_LCD \ LCD Sample
30324 \ \ if write : %xxxx_WWWW --
30325 \ \ if read : -- %0000_RRRR
30326 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30327 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30328 0= IF \ write LCD bits pattern
30329 AND.B #LCD_DB,TOS \
30330 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30331 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30334 THEN \ read LCD bits pattern
30337 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30338 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30339 AND.B #LCD_DB,TOS \
30343 CODE LCD_WRC \ char -- Write Char
30344 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30346 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
30347 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
30348 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30349 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30350 COLON \ high level word starts here
30351 TOP_LCD 2 20_US \ write high nibble first
30355 CODE LCD_WRF \ func -- Write Fonction
30356 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30360 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
30361 : LCD_HOME $02 LCD_WRF 100 20_us ;
30363 \ [UNDEFINED] OR [IF]
30365 \ \ https://forth-standard.org/standard/core/OR
30366 \ \ C OR x1 x2 -- x3 logical OR
30374 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
30375 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
30376 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
30377 \ : LCD_FN_SET $20 OR LCD_WrF ;
30378 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
30379 \ : LCD_GOTO $80 OR LCD_WrF ;
30382 \ CODE LCD_RDS \ -- status Read Status
30383 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30384 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30385 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30386 \ COLON \ starts a FORTH word
30387 \ TOP_LCD 2 20_us \ -- %0000_HHHH
30388 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
30389 \ HI2LO \ switch from FORTH to assembler
30390 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
30391 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
30392 \ MOV @RSP+,IP \ restore IP saved by COLON
30396 \ CODE LCD_RDC \ -- char Read Char
30397 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30402 \ ******************************\
30403 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30404 \ ******************************\
30405 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
30406 BIT.B #SW2,&SW2_IN \ test switch S2
30407 0= IF \ case of switch S2 pressed
30408 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30410 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
30413 BIT.B #SW1,&SW1_IN \ test switch S1 input
30414 0= IF \ case of Switch S1 pressed
30415 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30417 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30424 \ ******************************\
30425 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
30426 \ ******************************\
30427 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30428 \ ******************************\
30429 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30430 \ \ SMclock = 8|16|24 MHz
30431 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30432 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30433 \ \ SR(9)=new Toggle bit memory (ADD on)
30434 \ ******************************\
30435 \ RC5_FirstStartBitHalfCycle: \
30436 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30437 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
30438 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
30440 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
30441 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
30443 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
30444 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
30446 MOV #1778,X \ RC5_Period * 1us
30447 MOV #14,W \ count of loop
30449 \ ******************************\
30450 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
30451 \ ******************************\ |
30452 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30453 \ RC5_Compute_3/4_Period: \ |
30454 RRUM #1,X \ X=1/2 cycle |
30457 ADD X,Y \ Y=3/4 cycle
30458 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
30460 \ ******************************\
30461 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30462 \ ******************************\
30463 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30464 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
30465 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30466 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30467 SUB #1,W \ decrement count loop
30468 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
30469 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30470 0<> WHILE \ ----> out of loop ----+
30471 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30473 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
30474 CMP Y,X \ 1 | cycle time out of bound ?
30475 U>= IF \ 2 ^ | yes:
30476 BIC #$30,&RC5_TIM_CTL \ | | stop timer
30477 GOTO FW1 \ | | quit on truncated RC5 message
30479 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
30481 REPEAT \ ----> loop back --+ | with X = new RC5_period value
30482 \ ******************************\ |
30483 \ RC5_SampleEndOf: \ <---------------------+
30484 \ ******************************\
30485 BIC #$30,&RC5_TIM_CTL \ stop timer
30486 \ ******************************\
30487 \ RC5_ComputeNewRC5word \
30488 \ ******************************\
30489 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
30490 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
30491 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
30492 \ ******************************\
30493 \ RC5_ComputeC6bit \
30494 \ ******************************\
30495 BIT #BIT14,T \ test /C6 bit in T
30496 0= IF BIS #BIT6,X \ set C6 bit in X
30497 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
30498 \ ******************************\
30499 \ RC5_CommandByteIsDone \ -- BASE RC5_code
30500 \ ******************************\
30501 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
30502 \ ******************************\
30503 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
30504 XOR @RSP,T \ (new XOR old) Toggle bits
30505 BIT #UF10,T \ repeated RC5_command ?
30506 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
30507 XOR #UF10,0(RSP) \ 5 toggle bit memory
30508 \ ******************************\
30509 \ Display IR_RC5 code \
30510 \ ******************************\
30511 SUB #8,PSP \ TOS -- x x x x TOS
30512 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
30513 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
30514 MOV #$10,&BASEADR \ set hexadecimal base
30515 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
30516 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
30517 LO2HI \ switch from assembler to FORTH
30518 LCD_CLEAR \ set LCD cursor at home
30519 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
30520 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
30521 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
30522 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
30523 HI2LO \ -- switch from FORTH to assembler
30524 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
30525 MOV @PSP+,TOS \ -- TOS
30527 MOV @RSP+,SR \ restore SR flags
30528 BIC #%1111_1000,SR \ but force CPU Active Mode
30529 RET \ (instead of RETI)
30533 \ ------------------------------\
30534 HDNCODE STOP_R2L \ define new STOP_APP
30535 \ ------------------------------\
30536 CMP #RET_ADR,&{RC5TOLCD}+8 \
30537 0<> IF \ if previous START executing
30538 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
30539 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
30540 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
30541 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
30542 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
30543 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
30544 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
30545 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
30546 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
30547 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
30552 \ ------------------------------\
30554 \ ------------------------------\
30555 BW1 \ <-- INI_R2L for some events
30557 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30559 ." RC5toLCD is removed,"
30560 ." type START to restart"
30563 \ ------------------------------\
30565 \ ------------------------------\
30566 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
30567 \ ------------------------------\
30569 \ ------------------------------\
30570 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
30571 \ ------------------------------\
30572 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
30573 \ ------------------------------\
30574 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
30575 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
30577 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
30578 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
30580 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
30581 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
30582 \ CMP #4,TOS \ hardware RST
30583 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
30584 \ CMP #2,TOS \ Power_ON event
30585 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30587 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30589 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30591 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30592 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
30593 \ ------------------------------\
30594 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30595 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30596 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30597 \ -- \ID input divider \ 10 = /4
30598 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30599 \ - \TBCLR TimerB Clear
30602 \ -------------------------------\
30603 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30604 \ -- \CM Capture Mode
30609 \ --- \OUTMOD \ 011 = set/reset
30615 \ -------------------------------\
30617 \ -------------------------------\
30619 \ ------------------------------\
30620 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30621 \ ------------------------------\
30622 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30623 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30624 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30625 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30627 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30628 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30630 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30631 \ ------------------------------\
30632 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30633 \ ------------------------------\
30634 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30635 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30636 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30637 \ ------------------------------\
30638 BIS.B #LCDVo,&LCDVo_DIR \
30639 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30640 \ ------------------------------\
30641 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30642 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30643 \ ------------------------------\
30644 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30645 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30646 \ ******************************\
30648 \ ******************************\
30649 BIS.B #RC5,&IR_IE \ enable RC5_Int
30650 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30651 \ ******************************\
30652 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30653 \ ******************************\
30654 \ %01 0001 0100 \ TAxCTL
30655 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30656 \ -- \ ID divided by 1
30657 \ -- \ MC MODE = up to TAxCCRn
30658 \ - \ TACLR clear timer count
30661 \ ------------------------------\
30662 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30663 \ ------------------------------\
30665 \ --- \ TAIDEX pre divisor
30666 \ ------------------------------\
30667 \ %0000 0000 0000 0101 \ TAxCCR0
30668 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30669 \ ------------------------------\
30670 \ %0000 0000 0001 0000 \ TAxCCTL0
30671 \ - \ CAP capture/compare mode = compare
30674 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30675 \ ------------------------------\
30676 \ define LPM mode for ACCEPT \
30677 \ ------------------------------\
30678 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
30679 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30680 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30681 \ ------------------------------\
30683 \ ------------------------------\
30685 \ ------------------------------\
30686 #1000 20_US \ 1- wait 20 ms
30687 %011 TOP_LCD \ 2- send DB5=DB4=1
30688 #205 20_US \ 3- wait 4,1 ms
30689 %011 TOP_LCD \ 4- send again DB5=DB4=1
30690 #5 20_US \ 5- wait 0,1 ms
30691 %011 TOP_LCD \ 6- send again again DB5=DB4=1
30692 #2 20_US \ wait 40 us = LCD cycle
30693 %010 TOP_LCD \ 7- send DB5=1 DB4=0
30694 #2 20_US \ wait 40 us = LCD cycle
30695 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30696 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30697 LCD_CLEAR \ 10- "LCD_Clear"
30698 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30699 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30700 LCD_CLEAR \ 10- "LCD_Clear"
30701 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30702 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30703 CR ." I love you" \ display message on LCD
30704 ['] CR >BODY IS CR \ CR executes its default value
30705 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
30706 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30709 \ ------------------------------\
30711 \ ------------------------------\
30712 CODE START \ this routine replaces WARM and COLD default values by these of this application.
30713 \ ------------------------------\
30714 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
30715 0= IF \ if not done, customizes MARKER_DOES
30716 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
30717 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
30718 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
30719 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
30720 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30721 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
30722 MOV #RC5_INT,&IR_VEC \ init interrupt vector
30723 MOV #INI_R2L,PC \ then execute new INI_APP, without return
30727 \ ------------------------------\
30730 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
30732 MARKER {RC5TOLCD} \ restore the state before MARKER definition
30733 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
30734 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
30735 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
30736 \ {RC5TOLCD}+14: make room to save previous IR_VEC
30738 [UNDEFINED] CONSTANT [IF]
30739 \ https://forth-standard.org/standard/core/CONSTANT
30740 \ CONSTANT <name> n -- define a Forth CONSTANT
30744 MOV TOS,-2(W) \ PFA = n
30751 [UNDEFINED] STATE [IF]
30752 \ https://forth-standard.org/standard/core/STATE
30753 \ STATE -- a-addr holds compiler state
30754 STATEADR CONSTANT STATE
30758 \ https://forth-standard.org/standard/core/Equal
30759 \ = x1 x2 -- flag test x1=x2
30766 XOR #-1,TOS \ 1 flag Z = 1
30771 [UNDEFINED] IF [IF] \ define IF and THEN
30772 \ https://forth-standard.org/standard/core/IF
30773 \ IF -- IFadr initialize conditional forward branch
30774 CODE IF \ immediate
30777 MOV &DP,TOS \ -- HERE
30778 ADD #4,&DP \ compile one word, reserve one word
30779 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
30780 ADD #2,TOS \ -- HERE+2=IFadr
30784 \ https://forth-standard.org/standard/core/THEN
30785 \ THEN IFadr -- resolve forward branch
30786 CODE THEN \ immediate
30787 MOV &DP,0(TOS) \ -- IFadr
30793 [UNDEFINED] ELSE [IF]
30794 \ https://forth-standard.org/standard/core/ELSE
30795 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
30796 CODE ELSE \ immediate
30797 ADD #4,&DP \ make room to compile two words
30798 MOV &DP,W \ W=HERE+4
30800 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
30802 MOV W,TOS \ -- ELSEadr
30807 [UNDEFINED] IS [IF] \ define DEFER! and IS
30809 \ https://forth-standard.org/standard/core/DEFERStore
30810 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
30811 CODE DEFER! \ xt2 xt1 --
30812 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
30817 \ https://forth-standard.org/standard/core/IS
30820 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
30821 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
30822 \ or in a definition : ... ['] U. IS DISPLAY ...
30823 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
30825 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
30829 IF POSTPONE ['] POSTPONE DEFER!
30835 [UNDEFINED] >BODY [IF]
30836 \ https://forth-standard.org/standard/core/toBODY
30837 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
30844 \ CODE 20uS \ n -- 8MHz version
30845 \ BEGIN \ 4 + 16 ~ loop
30846 \ MOV #39,rDOCON \ 39
30853 \ MOV #XDOCON,rDOCON \ 2
30858 CODE 20_US \ n -- n * 20 us
30859 BEGIN \ here we presume that LCD_TIM_IFG = 1...
30861 BIT #1,&LCD_TIM_CTL \ 3
30862 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
30863 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
30865 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
30870 CODE TOP_LCD \ LCD Sample
30871 \ \ if write : %xxxx_WWWW --
30872 \ \ if read : -- %0000_RRRR
30873 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30874 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30875 0= IF \ write LCD bits pattern
30876 AND.B #LCD_DB,TOS \
30877 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30878 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30881 THEN \ read LCD bits pattern
30884 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30885 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30886 AND.B #LCD_DB,TOS \
30890 CODE LCD_WRC \ char -- Write Char
30891 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30893 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
30894 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
30895 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30896 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30897 COLON \ high level word starts here
30898 TOP_LCD 2 20_US \ write high nibble first
30902 CODE LCD_WRF \ func -- Write Fonction
30903 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30907 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
30908 : LCD_HOME $02 LCD_WRF 100 20_us ;
30910 \ [UNDEFINED] OR [IF]
30912 \ \ https://forth-standard.org/standard/core/OR
30913 \ \ C OR x1 x2 -- x3 logical OR
30921 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
30922 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
30923 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
30924 \ : LCD_FN_SET $20 OR LCD_WrF ;
30925 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
30926 \ : LCD_GOTO $80 OR LCD_WrF ;
30929 \ CODE LCD_RDS \ -- status Read Status
30930 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30931 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30932 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30933 \ COLON \ starts a FORTH word
30934 \ TOP_LCD 2 20_us \ -- %0000_HHHH
30935 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
30936 \ HI2LO \ switch from FORTH to assembler
30937 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
30938 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
30939 \ MOV @RSP+,IP \ restore IP saved by COLON
30943 \ CODE LCD_RDC \ -- char Read Char
30944 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30949 \ ******************************\
30950 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30951 \ ******************************\
30952 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
30953 BIT.B #SW2,&SW2_IN \ test switch S2
30954 0= IF \ case of switch S2 pressed
30955 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30957 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
30960 BIT.B #SW1,&SW1_IN \ test switch S1 input
30961 0= IF \ case of Switch S1 pressed
30962 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30964 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30971 \ ******************************\
30972 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
30973 \ ******************************\
30974 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30975 \ ******************************\
30976 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30977 \ \ SMclock = 8|16|24 MHz
30978 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30979 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30980 \ \ SR(9)=new Toggle bit memory (ADD on)
30981 \ ******************************\
30982 \ RC5_FirstStartBitHalfCycle: \
30983 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30984 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
30985 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
30987 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
30988 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
30990 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
30991 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
30993 MOV #1778,X \ RC5_Period * 1us
30994 MOV #14,W \ count of loop
30996 \ ******************************\
30997 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
30998 \ ******************************\ |
30999 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31000 \ RC5_Compute_3/4_Period: \ |
31001 RRUM #1,X \ X=1/2 cycle |
31004 ADD X,Y \ Y=3/4 cycle
31005 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
31007 \ ******************************\
31008 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31009 \ ******************************\
31010 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31011 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
31012 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31013 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31014 SUB #1,W \ decrement count loop
31015 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
31016 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31017 0<> WHILE \ ----> out of loop ----+
31018 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31020 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
31021 CMP Y,X \ 1 | cycle time out of bound ?
31022 U>= IF \ 2 ^ | yes:
31023 BIC #$30,&RC5_TIM_CTL \ | | stop timer
31024 GOTO FW1 \ | | quit on truncated RC5 message
31026 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
31028 REPEAT \ ----> loop back --+ | with X = new RC5_period value
31029 \ ******************************\ |
31030 \ RC5_SampleEndOf: \ <---------------------+
31031 \ ******************************\
31032 BIC #$30,&RC5_TIM_CTL \ stop timer
31033 \ ******************************\
31034 \ RC5_ComputeNewRC5word \
31035 \ ******************************\
31036 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
31037 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
31038 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
31039 \ ******************************\
31040 \ RC5_ComputeC6bit \
31041 \ ******************************\
31042 BIT #BIT14,T \ test /C6 bit in T
31043 0= IF BIS #BIT6,X \ set C6 bit in X
31044 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
31045 \ ******************************\
31046 \ RC5_CommandByteIsDone \ -- BASE RC5_code
31047 \ ******************************\
31048 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
31049 \ ******************************\
31050 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
31051 XOR @RSP,T \ (new XOR old) Toggle bits
31052 BIT #UF10,T \ repeated RC5_command ?
31053 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
31054 XOR #UF10,0(RSP) \ 5 toggle bit memory
31055 \ ******************************\
31056 \ Display IR_RC5 code \
31057 \ ******************************\
31058 SUB #8,PSP \ TOS -- x x x x TOS
31059 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
31060 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
31061 MOV #$10,&BASEADR \ set hexadecimal base
31062 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
31063 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
31064 LO2HI \ switch from assembler to FORTH
31065 LCD_CLEAR \ set LCD cursor at home
31066 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
31067 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
31068 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
31069 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
31070 HI2LO \ -- switch from FORTH to assembler
31071 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
31072 MOV @PSP+,TOS \ -- TOS
31074 MOV @RSP+,SR \ restore SR flags
31075 BIC #%1111_1000,SR \ but force CPU Active Mode
31076 RET \ (instead of RETI)
31080 \ ------------------------------\
31081 HDNCODE STOP_R2L \ define new STOP_APP
31082 \ ------------------------------\
31083 CMP #RET_ADR,&{RC5TOLCD}+8 \
31084 0<> IF \ if previous START executing
31085 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
31086 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
31087 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
31088 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
31089 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
31090 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
31091 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
31092 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
31093 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
31094 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
31099 \ ------------------------------\
31101 \ ------------------------------\
31102 BW1 \ <-- INI_R2L for some events
31104 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
31106 ." RC5toLCD is removed,"
31107 ." type START to restart"
31110 \ ------------------------------\
31112 \ ------------------------------\
31113 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
31114 \ ------------------------------\
31116 \ ------------------------------\
31117 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
31118 \ ------------------------------\
31119 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
31120 \ ------------------------------\
31121 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
31122 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
31124 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
31125 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
31127 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
31128 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
31129 \ CMP #4,TOS \ hardware RST
31130 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
31131 \ CMP #2,TOS \ Power_ON event
31132 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
31134 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
31136 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
31138 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
31139 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
31140 \ ------------------------------\
31141 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
31142 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31143 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31144 \ -- \ID input divider \ 10 = /4
31145 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
31146 \ - \TBCLR TimerB Clear
31149 \ -------------------------------\
31150 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31151 \ -- \CM Capture Mode
31156 \ --- \OUTMOD \ 011 = set/reset
31162 \ -------------------------------\
31164 \ -------------------------------\
31166 \ ------------------------------\
31167 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
31168 \ ------------------------------\
31169 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
31170 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
31171 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
31172 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
31174 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
31175 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
31177 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
31178 \ ------------------------------\
31179 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
31180 \ ------------------------------\
31181 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
31182 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
31183 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31184 \ ------------------------------\
31185 BIS.B #LCDVo,&LCDVo_DIR \
31186 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
31187 \ ------------------------------\
31188 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31189 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31190 \ ------------------------------\
31191 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31192 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31193 \ ******************************\
31195 \ ******************************\
31196 BIS.B #RC5,&IR_IE \ enable RC5_Int
31197 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31198 \ ******************************\
31199 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
31200 \ ******************************\
31201 \ %01 0001 0100 \ TAxCTL
31202 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
31203 \ -- \ ID divided by 1
31204 \ -- \ MC MODE = up to TAxCCRn
31205 \ - \ TACLR clear timer count
31208 \ ------------------------------\
31209 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
31210 \ ------------------------------\
31212 \ --- \ TAIDEX pre divisor
31213 \ ------------------------------\
31214 \ %0000 0000 0000 0101 \ TAxCCR0
31215 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
31216 \ ------------------------------\
31217 \ %0000 0000 0001 0000 \ TAxCCTL0
31218 \ - \ CAP capture/compare mode = compare
31221 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
31222 \ ------------------------------\
31223 \ define LPM mode for ACCEPT \
31224 \ ------------------------------\
31225 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
31226 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31227 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31228 \ ------------------------------\
31230 \ ------------------------------\
31232 \ ------------------------------\
31233 #1000 20_US \ 1- wait 20 ms
31234 %011 TOP_LCD \ 2- send DB5=DB4=1
31235 #205 20_US \ 3- wait 4,1 ms
31236 %011 TOP_LCD \ 4- send again DB5=DB4=1
31237 #5 20_US \ 5- wait 0,1 ms
31238 %011 TOP_LCD \ 6- send again again DB5=DB4=1
31239 #2 20_US \ wait 40 us = LCD cycle
31240 %010 TOP_LCD \ 7- send DB5=1 DB4=0
31241 #2 20_US \ wait 40 us = LCD cycle
31242 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31243 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31244 LCD_CLEAR \ 10- "LCD_Clear"
31245 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31246 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31247 LCD_CLEAR \ 10- "LCD_Clear"
31248 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31249 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31250 CR ." I love you" \ display message on LCD
31251 ['] CR >BODY IS CR \ CR executes its default value
31252 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
31253 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
31256 \ ------------------------------\
31258 \ ------------------------------\
31259 CODE START \ this routine replaces WARM and COLD default values by these of this application.
31260 \ ------------------------------\
31261 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
31262 0= IF \ if not done, customizes MARKER_DOES
31263 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
31264 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
31265 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
31266 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
31267 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
31268 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
31269 MOV #RC5_INT,&IR_VEC \ init interrupt vector
31270 MOV #INI_R2L,PC \ then execute new INI_APP, without return
31274 \ ------------------------------\
31277 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
31279 MARKER {RC5TOLCD} \ restore the state before MARKER definition
31280 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
31281 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
31282 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
31283 \ {RC5TOLCD}+14: make room to save previous IR_VEC
31285 [UNDEFINED] CONSTANT [IF]
31286 \ https://forth-standard.org/standard/core/CONSTANT
31287 \ CONSTANT <name> n -- define a Forth CONSTANT
31291 MOV TOS,-2(W) \ PFA = n
31298 [UNDEFINED] STATE [IF]
31299 \ https://forth-standard.org/standard/core/STATE
31300 \ STATE -- a-addr holds compiler state
31301 STATEADR CONSTANT STATE
31305 \ https://forth-standard.org/standard/core/Equal
31306 \ = x1 x2 -- flag test x1=x2
31313 XOR #-1,TOS \ 1 flag Z = 1
31318 [UNDEFINED] IF [IF] \ define IF and THEN
31319 \ https://forth-standard.org/standard/core/IF
31320 \ IF -- IFadr initialize conditional forward branch
31321 CODE IF \ immediate
31324 MOV &DP,TOS \ -- HERE
31325 ADD #4,&DP \ compile one word, reserve one word
31326 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
31327 ADD #2,TOS \ -- HERE+2=IFadr
31331 \ https://forth-standard.org/standard/core/THEN
31332 \ THEN IFadr -- resolve forward branch
31333 CODE THEN \ immediate
31334 MOV &DP,0(TOS) \ -- IFadr
31340 [UNDEFINED] ELSE [IF]
31341 \ https://forth-standard.org/standard/core/ELSE
31342 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
31343 CODE ELSE \ immediate
31344 ADD #4,&DP \ make room to compile two words
31345 MOV &DP,W \ W=HERE+4
31347 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
31349 MOV W,TOS \ -- ELSEadr
31354 [UNDEFINED] IS [IF] \ define DEFER! and IS
31356 \ https://forth-standard.org/standard/core/DEFERStore
31357 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
31358 CODE DEFER! \ xt2 xt1 --
31359 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
31364 \ https://forth-standard.org/standard/core/IS
31367 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
31368 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
31369 \ or in a definition : ... ['] U. IS DISPLAY ...
31370 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
31372 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
31376 IF POSTPONE ['] POSTPONE DEFER!
31382 [UNDEFINED] >BODY [IF]
31383 \ https://forth-standard.org/standard/core/toBODY
31384 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
31391 \ CODE 20uS \ n -- 8MHz version
31392 \ BEGIN \ 4 + 16 ~ loop
31393 \ MOV #39,rDOCON \ 39
31400 \ MOV #XDOCON,rDOCON \ 2
31405 CODE 20_US \ n -- n * 20 us
31406 BEGIN \ here we presume that LCD_TIM_IFG = 1...
31408 BIT #1,&LCD_TIM_CTL \ 3
31409 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
31410 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
31412 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
31417 CODE TOP_LCD \ LCD Sample
31418 \ \ if write : %xxxx_WWWW --
31419 \ \ if read : -- %0000_RRRR
31420 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31421 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31422 0= IF \ write LCD bits pattern
31423 AND.B #LCD_DB,TOS \
31424 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31425 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31428 THEN \ read LCD bits pattern
31431 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31432 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31433 AND.B #LCD_DB,TOS \
31437 CODE LCD_WRC \ char -- Write Char
31438 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31440 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
31441 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
31442 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31443 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31444 COLON \ high level word starts here
31445 TOP_LCD 2 20_US \ write high nibble first
31449 CODE LCD_WRF \ func -- Write Fonction
31450 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31454 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
31455 : LCD_HOME $02 LCD_WRF 100 20_us ;
31457 \ [UNDEFINED] OR [IF]
31459 \ \ https://forth-standard.org/standard/core/OR
31460 \ \ C OR x1 x2 -- x3 logical OR
31468 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
31469 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
31470 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
31471 \ : LCD_FN_SET $20 OR LCD_WrF ;
31472 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
31473 \ : LCD_GOTO $80 OR LCD_WrF ;
31476 \ CODE LCD_RDS \ -- status Read Status
31477 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31478 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31479 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31480 \ COLON \ starts a FORTH word
31481 \ TOP_LCD 2 20_us \ -- %0000_HHHH
31482 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
31483 \ HI2LO \ switch from FORTH to assembler
31484 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
31485 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
31486 \ MOV @RSP+,IP \ restore IP saved by COLON
31490 \ CODE LCD_RDC \ -- char Read Char
31491 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31496 \ ******************************\
31497 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31498 \ ******************************\
31499 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
31500 BIT.B #SW2,&SW2_IN \ test switch S2
31501 0= IF \ case of switch S2 pressed
31502 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
31504 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
31507 BIT.B #SW1,&SW1_IN \ test switch S1 input
31508 0= IF \ case of Switch S1 pressed
31509 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
31511 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
31518 \ ******************************\
31519 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
31520 \ ******************************\
31521 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31522 \ ******************************\
31523 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31524 \ \ SMclock = 8|16|24 MHz
31525 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
31526 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
31527 \ \ SR(9)=new Toggle bit memory (ADD on)
31528 \ ******************************\
31529 \ RC5_FirstStartBitHalfCycle: \
31530 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
31531 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
31532 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
31534 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
31535 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
31537 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
31538 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
31540 MOV #1778,X \ RC5_Period * 1us
31541 MOV #14,W \ count of loop
31543 \ ******************************\
31544 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
31545 \ ******************************\ |
31546 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31547 \ RC5_Compute_3/4_Period: \ |
31548 RRUM #1,X \ X=1/2 cycle |
31551 ADD X,Y \ Y=3/4 cycle
31552 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
31554 \ ******************************\
31555 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31556 \ ******************************\
31557 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31558 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
31559 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31560 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31561 SUB #1,W \ decrement count loop
31562 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
31563 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31564 0<> WHILE \ ----> out of loop ----+
31565 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31567 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
31568 CMP Y,X \ 1 | cycle time out of bound ?
31569 U>= IF \ 2 ^ | yes:
31570 BIC #$30,&RC5_TIM_CTL \ | | stop timer
31571 GOTO FW1 \ | | quit on truncated RC5 message
31573 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
31575 REPEAT \ ----> loop back --+ | with X = new RC5_period value
31576 \ ******************************\ |
31577 \ RC5_SampleEndOf: \ <---------------------+
31578 \ ******************************\
31579 BIC #$30,&RC5_TIM_CTL \ stop timer
31580 \ ******************************\
31581 \ RC5_ComputeNewRC5word \
31582 \ ******************************\
31583 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
31584 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
31585 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
31586 \ ******************************\
31587 \ RC5_ComputeC6bit \
31588 \ ******************************\
31589 BIT #BIT14,T \ test /C6 bit in T
31590 0= IF BIS #BIT6,X \ set C6 bit in X
31591 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
31592 \ ******************************\
31593 \ RC5_CommandByteIsDone \ -- BASE RC5_code
31594 \ ******************************\
31595 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
31596 \ ******************************\
31597 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
31598 XOR @RSP,T \ (new XOR old) Toggle bits
31599 BIT #UF10,T \ repeated RC5_command ?
31600 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
31601 XOR #UF10,0(RSP) \ 5 toggle bit memory
31602 \ ******************************\
31603 \ Display IR_RC5 code \
31604 \ ******************************\
31605 SUB #8,PSP \ TOS -- x x x x TOS
31606 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
31607 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
31608 MOV #$10,&BASEADR \ set hexadecimal base
31609 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
31610 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
31611 LO2HI \ switch from assembler to FORTH
31612 LCD_CLEAR \ set LCD cursor at home
31613 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
31614 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
31615 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
31616 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
31617 HI2LO \ -- switch from FORTH to assembler
31618 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
31619 MOV @PSP+,TOS \ -- TOS
31621 MOV @RSP+,SR \ restore SR flags
31622 BIC #%1111_1000,SR \ but force CPU Active Mode
31623 RET \ (instead of RETI)
31627 \ ------------------------------\
31628 HDNCODE STOP_R2L \ define new STOP_APP
31629 \ ------------------------------\
31630 CMP #RET_ADR,&{RC5TOLCD}+8 \
31631 0<> IF \ if previous START executing
31632 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
31633 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
31634 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
31635 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
31636 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
31637 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
31638 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
31639 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
31640 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
31641 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
31646 \ ------------------------------\
31648 \ ------------------------------\
31649 BW1 \ <-- INI_R2L for some events
31651 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
31653 ." RC5toLCD is removed,"
31654 ." type START to restart"
31657 \ ------------------------------\
31659 \ ------------------------------\
31660 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
31661 \ ------------------------------\
31663 \ ------------------------------\
31664 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
31665 \ ------------------------------\
31666 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
31667 \ ------------------------------\
31668 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
31669 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
31671 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
31672 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
31674 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
31675 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
31676 \ CMP #4,TOS \ hardware RST
31677 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
31678 \ CMP #2,TOS \ Power_ON event
31679 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
31681 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
31683 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
31685 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
31686 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
31687 \ ------------------------------\
31688 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
31689 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31690 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31691 \ -- \ID input divider \ 10 = /4
31692 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
31693 \ - \TBCLR TimerB Clear
31696 \ -------------------------------\
31697 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31698 \ -- \CM Capture Mode
31703 \ --- \OUTMOD \ 011 = set/reset
31709 \ -------------------------------\
31711 \ -------------------------------\
31713 \ ------------------------------\
31714 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
31715 \ ------------------------------\
31716 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
31717 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
31718 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
31719 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
31721 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
31722 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
31724 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
31725 \ ------------------------------\
31726 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
31727 \ ------------------------------\
31728 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
31729 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
31730 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31731 \ ------------------------------\
31732 BIS.B #LCDVo,&LCDVo_DIR \
31733 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
31734 \ ------------------------------\
31735 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31736 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31737 \ ------------------------------\
31738 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31739 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31740 \ ******************************\
31742 \ ******************************\
31743 BIS.B #RC5,&IR_IE \ enable RC5_Int
31744 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31745 \ ******************************\
31746 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
31747 \ ******************************\
31748 \ %01 0001 0100 \ TAxCTL
31749 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
31750 \ -- \ ID divided by 1
31751 \ -- \ MC MODE = up to TAxCCRn
31752 \ - \ TACLR clear timer count
31755 \ ------------------------------\
31756 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
31757 \ ------------------------------\
31759 \ --- \ TAIDEX pre divisor
31760 \ ------------------------------\
31761 \ %0000 0000 0000 0101 \ TAxCCR0
31762 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
31763 \ ------------------------------\
31764 \ %0000 0000 0001 0000 \ TAxCCTL0
31765 \ - \ CAP capture/compare mode = compare
31768 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
31769 \ ------------------------------\
31770 \ define LPM mode for ACCEPT \
31771 \ ------------------------------\
31772 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
31773 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31774 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31775 \ ------------------------------\
31777 \ ------------------------------\
31779 \ ------------------------------\
31780 #1000 20_US \ 1- wait 20 ms
31781 %011 TOP_LCD \ 2- send DB5=DB4=1
31782 #205 20_US \ 3- wait 4,1 ms
31783 %011 TOP_LCD \ 4- send again DB5=DB4=1
31784 #5 20_US \ 5- wait 0,1 ms
31785 %011 TOP_LCD \ 6- send again again DB5=DB4=1
31786 #2 20_US \ wait 40 us = LCD cycle
31787 %010 TOP_LCD \ 7- send DB5=1 DB4=0
31788 #2 20_US \ wait 40 us = LCD cycle
31789 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31790 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31791 LCD_CLEAR \ 10- "LCD_Clear"
31792 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31793 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31794 LCD_CLEAR \ 10- "LCD_Clear"
31795 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31796 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31797 CR ." I love you" \ display message on LCD
31798 ['] CR >BODY IS CR \ CR executes its default value
31799 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
31800 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
31803 \ ------------------------------\
31805 \ ------------------------------\
31806 CODE START \ this routine replaces WARM and COLD default values by these of this application.
31807 \ ------------------------------\
31808 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
31809 0= IF \ if not done, customizes MARKER_DOES
31810 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
31811 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
31812 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
31813 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
31814 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
31815 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
31816 MOV #RC5_INT,&IR_VEC \ init interrupt vector
31817 MOV #INI_R2L,PC \ then execute new INI_APP, without return
31821 \ ------------------------------\
31824 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
31826 MARKER {RC5TOLCD} \ restore the state before MARKER definition
31827 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
31828 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
31829 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
31830 \ {RC5TOLCD}+14: make room to save previous IR_VEC
31832 [UNDEFINED] CONSTANT [IF]
31833 \ https://forth-standard.org/standard/core/CONSTANT
31834 \ CONSTANT <name> n -- define a Forth CONSTANT
31838 MOV TOS,-2(W) \ PFA = n
31845 [UNDEFINED] STATE [IF]
31846 \ https://forth-standard.org/standard/core/STATE
31847 \ STATE -- a-addr holds compiler state
31848 STATEADR CONSTANT STATE
31852 \ https://forth-standard.org/standard/core/Equal
31853 \ = x1 x2 -- flag test x1=x2
31860 XOR #-1,TOS \ 1 flag Z = 1
31865 [UNDEFINED] IF [IF] \ define IF and THEN
31866 \ https://forth-standard.org/standard/core/IF
31867 \ IF -- IFadr initialize conditional forward branch
31868 CODE IF \ immediate
31871 MOV &DP,TOS \ -- HERE
31872 ADD #4,&DP \ compile one word, reserve one word
31873 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
31874 ADD #2,TOS \ -- HERE+2=IFadr
31878 \ https://forth-standard.org/standard/core/THEN
31879 \ THEN IFadr -- resolve forward branch
31880 CODE THEN \ immediate
31881 MOV &DP,0(TOS) \ -- IFadr
31887 [UNDEFINED] ELSE [IF]
31888 \ https://forth-standard.org/standard/core/ELSE
31889 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
31890 CODE ELSE \ immediate
31891 ADD #4,&DP \ make room to compile two words
31892 MOV &DP,W \ W=HERE+4
31894 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
31896 MOV W,TOS \ -- ELSEadr
31901 [UNDEFINED] IS [IF] \ define DEFER! and IS
31903 \ https://forth-standard.org/standard/core/DEFERStore
31904 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
31905 CODE DEFER! \ xt2 xt1 --
31906 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
31911 \ https://forth-standard.org/standard/core/IS
31914 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
31915 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
31916 \ or in a definition : ... ['] U. IS DISPLAY ...
31917 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
31919 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
31923 IF POSTPONE ['] POSTPONE DEFER!
31929 [UNDEFINED] >BODY [IF]
31930 \ https://forth-standard.org/standard/core/toBODY
31931 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
31938 \ CODE 20uS \ n -- 8MHz version
31939 \ BEGIN \ 4 + 16 ~ loop
31940 \ MOV #39,rDOCON \ 39
31947 \ MOV #XDOCON,rDOCON \ 2
31952 CODE 20_US \ n -- n * 20 us
31953 BEGIN \ here we presume that LCD_TIM_IFG = 1...
31955 BIT #1,&LCD_TIM_CTL \ 3
31956 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
31957 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
31959 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
31964 CODE TOP_LCD \ LCD Sample
31965 \ \ if write : %xxxx_WWWW --
31966 \ \ if read : -- %0000_RRRR
31967 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31968 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31969 0= IF \ write LCD bits pattern
31970 AND.B #LCD_DB,TOS \
31971 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31972 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31975 THEN \ read LCD bits pattern
31978 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31979 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31980 AND.B #LCD_DB,TOS \
31984 CODE LCD_WRC \ char -- Write Char
31985 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31987 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
31988 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
31989 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31990 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31991 COLON \ high level word starts here
31992 TOP_LCD 2 20_US \ write high nibble first
31996 CODE LCD_WRF \ func -- Write Fonction
31997 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32001 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
32002 : LCD_HOME $02 LCD_WRF 100 20_us ;
32004 \ [UNDEFINED] OR [IF]
32006 \ \ https://forth-standard.org/standard/core/OR
32007 \ \ C OR x1 x2 -- x3 logical OR
32015 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
32016 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
32017 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
32018 \ : LCD_FN_SET $20 OR LCD_WrF ;
32019 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
32020 \ : LCD_GOTO $80 OR LCD_WrF ;
32023 \ CODE LCD_RDS \ -- status Read Status
32024 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32025 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32026 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32027 \ COLON \ starts a FORTH word
32028 \ TOP_LCD 2 20_us \ -- %0000_HHHH
32029 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
32030 \ HI2LO \ switch from FORTH to assembler
32031 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
32032 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
32033 \ MOV @RSP+,IP \ restore IP saved by COLON
32037 \ CODE LCD_RDC \ -- char Read Char
32038 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32043 \ ******************************\
32044 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32045 \ ******************************\
32046 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
32047 BIT.B #SW2,&SW2_IN \ test switch S2
32048 0= IF \ case of switch S2 pressed
32049 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
32051 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
32054 BIT.B #SW1,&SW1_IN \ test switch S1 input
32055 0= IF \ case of Switch S1 pressed
32056 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
32058 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
32065 \ ******************************\
32066 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
32067 \ ******************************\
32068 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32069 \ ******************************\
32070 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32071 \ \ SMclock = 8|16|24 MHz
32072 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
32073 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
32074 \ \ SR(9)=new Toggle bit memory (ADD on)
32075 \ ******************************\
32076 \ RC5_FirstStartBitHalfCycle: \
32077 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
32078 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
32079 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
32081 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
32082 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
32084 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
32085 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
32087 MOV #1778,X \ RC5_Period * 1us
32088 MOV #14,W \ count of loop
32090 \ ******************************\
32091 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
32092 \ ******************************\ |
32093 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
32094 \ RC5_Compute_3/4_Period: \ |
32095 RRUM #1,X \ X=1/2 cycle |
32098 ADD X,Y \ Y=3/4 cycle
32099 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
32101 \ ******************************\
32102 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
32103 \ ******************************\
32104 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32105 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
32106 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32107 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32108 SUB #1,W \ decrement count loop
32109 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
32110 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32111 0<> WHILE \ ----> out of loop ----+
32112 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
32114 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
32115 CMP Y,X \ 1 | cycle time out of bound ?
32116 U>= IF \ 2 ^ | yes:
32117 BIC #$30,&RC5_TIM_CTL \ | | stop timer
32118 GOTO FW1 \ | | quit on truncated RC5 message
32120 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
32122 REPEAT \ ----> loop back --+ | with X = new RC5_period value
32123 \ ******************************\ |
32124 \ RC5_SampleEndOf: \ <---------------------+
32125 \ ******************************\
32126 BIC #$30,&RC5_TIM_CTL \ stop timer
32127 \ ******************************\
32128 \ RC5_ComputeNewRC5word \
32129 \ ******************************\
32130 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
32131 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
32132 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
32133 \ ******************************\
32134 \ RC5_ComputeC6bit \
32135 \ ******************************\
32136 BIT #BIT14,T \ test /C6 bit in T
32137 0= IF BIS #BIT6,X \ set C6 bit in X
32138 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
32139 \ ******************************\
32140 \ RC5_CommandByteIsDone \ -- BASE RC5_code
32141 \ ******************************\
32142 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
32143 \ ******************************\
32144 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
32145 XOR @RSP,T \ (new XOR old) Toggle bits
32146 BIT #UF10,T \ repeated RC5_command ?
32147 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
32148 XOR #UF10,0(RSP) \ 5 toggle bit memory
32149 \ ******************************\
32150 \ Display IR_RC5 code \
32151 \ ******************************\
32152 SUB #8,PSP \ TOS -- x x x x TOS
32153 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
32154 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
32155 MOV #$10,&BASEADR \ set hexadecimal base
32156 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
32157 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
32158 LO2HI \ switch from assembler to FORTH
32159 LCD_CLEAR \ set LCD cursor at home
32160 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
32161 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
32162 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
32163 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
32164 HI2LO \ -- switch from FORTH to assembler
32165 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
32166 MOV @PSP+,TOS \ -- TOS
32168 MOV @RSP+,SR \ restore SR flags
32169 BIC #%1111_1000,SR \ but force CPU Active Mode
32170 RET \ (instead of RETI)
32174 \ ------------------------------\
32175 HDNCODE STOP_R2L \ define new STOP_APP
32176 \ ------------------------------\
32177 CMP #RET_ADR,&{RC5TOLCD}+8 \
32178 0<> IF \ if previous START executing
32179 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
32180 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
32181 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
32182 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
32183 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
32184 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
32185 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
32186 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
32187 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
32188 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
32193 \ ------------------------------\
32195 \ ------------------------------\
32196 BW1 \ <-- INI_R2L for some events
32198 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
32200 ." RC5toLCD is removed,"
32201 ." type START to restart"
32204 \ ------------------------------\
32206 \ ------------------------------\
32207 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
32208 \ ------------------------------\
32210 \ ------------------------------\
32211 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
32212 \ ------------------------------\
32213 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
32214 \ ------------------------------\
32215 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
32216 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
32218 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
32219 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
32221 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
32222 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
32223 \ CMP #4,TOS \ hardware RST
32224 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
32225 \ CMP #2,TOS \ Power_ON event
32226 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
32228 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
32230 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
32232 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
32233 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
32234 \ ------------------------------\
32235 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
32236 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32237 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32238 \ -- \ID input divider \ 10 = /4
32239 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
32240 \ - \TBCLR TimerB Clear
32243 \ -------------------------------\
32244 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32245 \ -- \CM Capture Mode
32250 \ --- \OUTMOD \ 011 = set/reset
32256 \ -------------------------------\
32258 \ -------------------------------\
32260 \ ------------------------------\
32261 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
32262 \ ------------------------------\
32263 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
32264 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
32265 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
32266 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
32268 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
32269 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
32271 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
32272 \ ------------------------------\
32273 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
32274 \ ------------------------------\
32275 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
32276 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
32277 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32278 \ ------------------------------\
32279 BIS.B #LCDVo,&LCDVo_DIR \
32280 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
32281 \ ------------------------------\
32282 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32283 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32284 \ ------------------------------\
32285 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32286 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32287 \ ******************************\
32289 \ ******************************\
32290 BIS.B #RC5,&IR_IE \ enable RC5_Int
32291 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32292 \ ******************************\
32293 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
32294 \ ******************************\
32295 \ %01 0001 0100 \ TAxCTL
32296 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
32297 \ -- \ ID divided by 1
32298 \ -- \ MC MODE = up to TAxCCRn
32299 \ - \ TACLR clear timer count
32302 \ ------------------------------\
32303 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
32304 \ ------------------------------\
32306 \ --- \ TAIDEX pre divisor
32307 \ ------------------------------\
32308 \ %0000 0000 0000 0101 \ TAxCCR0
32309 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
32310 \ ------------------------------\
32311 \ %0000 0000 0001 0000 \ TAxCCTL0
32312 \ - \ CAP capture/compare mode = compare
32315 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
32316 \ ------------------------------\
32317 \ define LPM mode for ACCEPT \
32318 \ ------------------------------\
32319 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
32320 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32321 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32322 \ ------------------------------\
32324 \ ------------------------------\
32326 \ ------------------------------\
32327 #1000 20_US \ 1- wait 20 ms
32328 %011 TOP_LCD \ 2- send DB5=DB4=1
32329 #205 20_US \ 3- wait 4,1 ms
32330 %011 TOP_LCD \ 4- send again DB5=DB4=1
32331 #5 20_US \ 5- wait 0,1 ms
32332 %011 TOP_LCD \ 6- send again again DB5=DB4=1
32333 #2 20_US \ wait 40 us = LCD cycle
32334 %010 TOP_LCD \ 7- send DB5=1 DB4=0
32335 #2 20_US \ wait 40 us = LCD cycle
32336 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32337 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32338 LCD_CLEAR \ 10- "LCD_Clear"
32339 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32340 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32341 LCD_CLEAR \ 10- "LCD_Clear"
32342 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32343 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32344 CR ." I love you" \ display message on LCD
32345 ['] CR >BODY IS CR \ CR executes its default value
32346 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
32347 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
32350 \ ------------------------------\
32352 \ ------------------------------\
32353 CODE START \ this routine replaces WARM and COLD default values by these of this application.
32354 \ ------------------------------\
32355 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
32356 0= IF \ if not done, customizes MARKER_DOES
32357 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
32358 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
32359 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
32360 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
32361 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
32362 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
32363 MOV #RC5_INT,&IR_VEC \ init interrupt vector
32364 MOV #INI_R2L,PC \ then execute new INI_APP, without return
32368 \ ------------------------------\
32371 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
32373 MARKER {RC5TOLCD} \ restore the state before MARKER definition
32374 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
32375 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
32376 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
32377 \ {RC5TOLCD}+14: make room to save previous IR_VEC
32379 [UNDEFINED] CONSTANT [IF]
32380 \ https://forth-standard.org/standard/core/CONSTANT
32381 \ CONSTANT <name> n -- define a Forth CONSTANT
32385 MOV TOS,-2(W) \ PFA = n
32392 [UNDEFINED] STATE [IF]
32393 \ https://forth-standard.org/standard/core/STATE
32394 \ STATE -- a-addr holds compiler state
32395 STATEADR CONSTANT STATE
32399 \ https://forth-standard.org/standard/core/Equal
32400 \ = x1 x2 -- flag test x1=x2
32407 XOR #-1,TOS \ 1 flag Z = 1
32412 [UNDEFINED] IF [IF] \ define IF and THEN
32413 \ https://forth-standard.org/standard/core/IF
32414 \ IF -- IFadr initialize conditional forward branch
32415 CODE IF \ immediate
32418 MOV &DP,TOS \ -- HERE
32419 ADD #4,&DP \ compile one word, reserve one word
32420 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
32421 ADD #2,TOS \ -- HERE+2=IFadr
32425 \ https://forth-standard.org/standard/core/THEN
32426 \ THEN IFadr -- resolve forward branch
32427 CODE THEN \ immediate
32428 MOV &DP,0(TOS) \ -- IFadr
32434 [UNDEFINED] ELSE [IF]
32435 \ https://forth-standard.org/standard/core/ELSE
32436 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
32437 CODE ELSE \ immediate
32438 ADD #4,&DP \ make room to compile two words
32439 MOV &DP,W \ W=HERE+4
32441 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
32443 MOV W,TOS \ -- ELSEadr
32448 [UNDEFINED] IS [IF] \ define DEFER! and IS
32450 \ https://forth-standard.org/standard/core/DEFERStore
32451 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
32452 CODE DEFER! \ xt2 xt1 --
32453 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
32458 \ https://forth-standard.org/standard/core/IS
32461 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
32462 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
32463 \ or in a definition : ... ['] U. IS DISPLAY ...
32464 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
32466 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
32470 IF POSTPONE ['] POSTPONE DEFER!
32476 [UNDEFINED] >BODY [IF]
32477 \ https://forth-standard.org/standard/core/toBODY
32478 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
32485 \ CODE 20uS \ n -- 8MHz version
32486 \ BEGIN \ 4 + 16 ~ loop
32487 \ MOV #39,rDOCON \ 39
32494 \ MOV #XDOCON,rDOCON \ 2
32499 CODE 20_US \ n -- n * 20 us
32500 BEGIN \ here we presume that LCD_TIM_IFG = 1...
32502 BIT #1,&LCD_TIM_CTL \ 3
32503 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
32504 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
32506 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
32511 CODE TOP_LCD \ LCD Sample
32512 \ \ if write : %xxxx_WWWW --
32513 \ \ if read : -- %0000_RRRR
32514 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
32515 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
32516 0= IF \ write LCD bits pattern
32517 AND.B #LCD_DB,TOS \
32518 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
32519 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32522 THEN \ read LCD bits pattern
32525 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32526 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
32527 AND.B #LCD_DB,TOS \
32531 CODE LCD_WRC \ char -- Write Char
32532 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32534 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
32535 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
32536 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
32537 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
32538 COLON \ high level word starts here
32539 TOP_LCD 2 20_US \ write high nibble first
32543 CODE LCD_WRF \ func -- Write Fonction
32544 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32548 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
32549 : LCD_HOME $02 LCD_WRF 100 20_us ;
32551 \ [UNDEFINED] OR [IF]
32553 \ \ https://forth-standard.org/standard/core/OR
32554 \ \ C OR x1 x2 -- x3 logical OR
32562 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
32563 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
32564 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
32565 \ : LCD_FN_SET $20 OR LCD_WrF ;
32566 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
32567 \ : LCD_GOTO $80 OR LCD_WrF ;
32570 \ CODE LCD_RDS \ -- status Read Status
32571 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32572 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32573 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32574 \ COLON \ starts a FORTH word
32575 \ TOP_LCD 2 20_us \ -- %0000_HHHH
32576 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
32577 \ HI2LO \ switch from FORTH to assembler
32578 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
32579 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
32580 \ MOV @RSP+,IP \ restore IP saved by COLON
32584 \ CODE LCD_RDC \ -- char Read Char
32585 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32590 \ ******************************\
32591 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32592 \ ******************************\
32593 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
32594 BIT.B #SW2,&SW2_IN \ test switch S2
32595 0= IF \ case of switch S2 pressed
32596 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
32598 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
32601 BIT.B #SW1,&SW1_IN \ test switch S1 input
32602 0= IF \ case of Switch S1 pressed
32603 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
32605 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
32612 \ ******************************\
32613 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
32614 \ ******************************\
32615 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32616 \ ******************************\
32617 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32618 \ \ SMclock = 8|16|24 MHz
32619 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
32620 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
32621 \ \ SR(9)=new Toggle bit memory (ADD on)
32622 \ ******************************\
32623 \ RC5_FirstStartBitHalfCycle: \
32624 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
32625 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
32626 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
32628 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
32629 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
32631 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
32632 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
32634 MOV #1778,X \ RC5_Period * 1us
32635 MOV #14,W \ count of loop
32637 \ ******************************\
32638 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
32639 \ ******************************\ |
32640 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
32641 \ RC5_Compute_3/4_Period: \ |
32642 RRUM #1,X \ X=1/2 cycle |
32645 ADD X,Y \ Y=3/4 cycle
32646 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
32648 \ ******************************\
32649 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
32650 \ ******************************\
32651 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32652 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
32653 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32654 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32655 SUB #1,W \ decrement count loop
32656 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
32657 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32658 0<> WHILE \ ----> out of loop ----+
32659 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
32661 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
32662 CMP Y,X \ 1 | cycle time out of bound ?
32663 U>= IF \ 2 ^ | yes:
32664 BIC #$30,&RC5_TIM_CTL \ | | stop timer
32665 GOTO FW1 \ | | quit on truncated RC5 message
32667 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
32669 REPEAT \ ----> loop back --+ | with X = new RC5_period value
32670 \ ******************************\ |
32671 \ RC5_SampleEndOf: \ <---------------------+
32672 \ ******************************\
32673 BIC #$30,&RC5_TIM_CTL \ stop timer
32674 \ ******************************\
32675 \ RC5_ComputeNewRC5word \
32676 \ ******************************\
32677 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
32678 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
32679 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
32680 \ ******************************\
32681 \ RC5_ComputeC6bit \
32682 \ ******************************\
32683 BIT #BIT14,T \ test /C6 bit in T
32684 0= IF BIS #BIT6,X \ set C6 bit in X
32685 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
32686 \ ******************************\
32687 \ RC5_CommandByteIsDone \ -- BASE RC5_code
32688 \ ******************************\
32689 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
32690 \ ******************************\
32691 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
32692 XOR @RSP,T \ (new XOR old) Toggle bits
32693 BIT #UF10,T \ repeated RC5_command ?
32694 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
32695 XOR #UF10,0(RSP) \ 5 toggle bit memory
32696 \ ******************************\
32697 \ Display IR_RC5 code \
32698 \ ******************************\
32699 SUB #8,PSP \ TOS -- x x x x TOS
32700 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
32701 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
32702 MOV #$10,&BASEADR \ set hexadecimal base
32703 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
32704 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
32705 LO2HI \ switch from assembler to FORTH
32706 LCD_CLEAR \ set LCD cursor at home
32707 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
32708 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
32709 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
32710 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
32711 HI2LO \ -- switch from FORTH to assembler
32712 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
32713 MOV @PSP+,TOS \ -- TOS
32715 MOV @RSP+,SR \ restore SR flags
32716 BIC #%1111_1000,SR \ but force CPU Active Mode
32717 RET \ (instead of RETI)
32721 \ ------------------------------\
32722 HDNCODE STOP_R2L \ define new STOP_APP
32723 \ ------------------------------\
32724 CMP #RET_ADR,&{RC5TOLCD}+8 \
32725 0<> IF \ if previous START executing
32726 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
32727 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
32728 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
32729 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
32730 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
32731 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
32732 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
32733 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
32734 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
32735 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
32740 \ ------------------------------\
32742 \ ------------------------------\
32743 BW1 \ <-- INI_R2L for some events
32745 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
32747 ." RC5toLCD is removed,"
32748 ." type START to restart"
32751 \ ------------------------------\
32753 \ ------------------------------\
32754 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
32755 \ ------------------------------\
32757 \ ------------------------------\
32758 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
32759 \ ------------------------------\
32760 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
32761 \ ------------------------------\
32762 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
32763 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
32765 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
32766 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
32768 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
32769 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
32770 \ CMP #4,TOS \ hardware RST
32771 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
32772 \ CMP #2,TOS \ Power_ON event
32773 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
32775 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
32777 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
32779 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
32780 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
32781 \ ------------------------------\
32782 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
32783 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32784 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32785 \ -- \ID input divider \ 10 = /4
32786 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
32787 \ - \TBCLR TimerB Clear
32790 \ -------------------------------\
32791 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32792 \ -- \CM Capture Mode
32797 \ --- \OUTMOD \ 011 = set/reset
32803 \ -------------------------------\
32805 \ -------------------------------\
32807 \ ------------------------------\
32808 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
32809 \ ------------------------------\
32810 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
32811 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
32812 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
32813 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
32815 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
32816 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
32818 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
32819 \ ------------------------------\
32820 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
32821 \ ------------------------------\
32822 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
32823 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
32824 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32825 \ ------------------------------\
32826 BIS.B #LCDVo,&LCDVo_DIR \
32827 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
32828 \ ------------------------------\
32829 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32830 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32831 \ ------------------------------\
32832 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32833 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32834 \ ******************************\
32836 \ ******************************\
32837 BIS.B #RC5,&IR_IE \ enable RC5_Int
32838 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32839 \ ******************************\
32840 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
32841 \ ******************************\
32842 \ %01 0001 0100 \ TAxCTL
32843 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
32844 \ -- \ ID divided by 1
32845 \ -- \ MC MODE = up to TAxCCRn
32846 \ - \ TACLR clear timer count
32849 \ ------------------------------\
32850 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
32851 \ ------------------------------\
32853 \ --- \ TAIDEX pre divisor
32854 \ ------------------------------\
32855 \ %0000 0000 0000 0101 \ TAxCCR0
32856 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
32857 \ ------------------------------\
32858 \ %0000 0000 0001 0000 \ TAxCCTL0
32859 \ - \ CAP capture/compare mode = compare
32862 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
32863 \ ------------------------------\
32864 \ define LPM mode for ACCEPT \
32865 \ ------------------------------\
32866 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
32867 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32868 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32869 \ ------------------------------\
32871 \ ------------------------------\
32873 \ ------------------------------\
32874 #1000 20_US \ 1- wait 20 ms
32875 %011 TOP_LCD \ 2- send DB5=DB4=1
32876 #205 20_US \ 3- wait 4,1 ms
32877 %011 TOP_LCD \ 4- send again DB5=DB4=1
32878 #5 20_US \ 5- wait 0,1 ms
32879 %011 TOP_LCD \ 6- send again again DB5=DB4=1
32880 #2 20_US \ wait 40 us = LCD cycle
32881 %010 TOP_LCD \ 7- send DB5=1 DB4=0
32882 #2 20_US \ wait 40 us = LCD cycle
32883 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32884 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32885 LCD_CLEAR \ 10- "LCD_Clear"
32886 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32887 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32888 LCD_CLEAR \ 10- "LCD_Clear"
32889 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32890 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32891 CR ." I love you" \ display message on LCD
32892 ['] CR >BODY IS CR \ CR executes its default value
32893 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
32894 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
32897 \ ------------------------------\
32899 \ ------------------------------\
32900 CODE START \ this routine replaces WARM and COLD default values by these of this application.
32901 \ ------------------------------\
32902 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
32903 0= IF \ if not done, customizes MARKER_DOES
32904 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
32905 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
32906 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
32907 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
32908 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
32909 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
32910 MOV #RC5_INT,&IR_VEC \ init interrupt vector
32911 MOV #INI_R2L,PC \ then execute new INI_APP, without return
32915 \ ------------------------------\
32918 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
32920 MARKER {RC5TOLCD} \ restore the state before MARKER definition
32921 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
32922 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
32923 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
32924 \ {RC5TOLCD}+14: make room to save previous IR_VEC
32926 [UNDEFINED] CONSTANT [IF]
32927 \ https://forth-standard.org/standard/core/CONSTANT
32928 \ CONSTANT <name> n -- define a Forth CONSTANT
32932 MOV TOS,-2(W) \ PFA = n
32939 [UNDEFINED] STATE [IF]
32940 \ https://forth-standard.org/standard/core/STATE
32941 \ STATE -- a-addr holds compiler state
32942 STATEADR CONSTANT STATE
32946 \ https://forth-standard.org/standard/core/Equal
32947 \ = x1 x2 -- flag test x1=x2
32954 XOR #-1,TOS \ 1 flag Z = 1
32959 [UNDEFINED] IF [IF] \ define IF and THEN
32960 \ https://forth-standard.org/standard/core/IF
32961 \ IF -- IFadr initialize conditional forward branch
32962 CODE IF \ immediate
32965 MOV &DP,TOS \ -- HERE
32966 ADD #4,&DP \ compile one word, reserve one word
32967 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
32968 ADD #2,TOS \ -- HERE+2=IFadr
32972 \ https://forth-standard.org/standard/core/THEN
32973 \ THEN IFadr -- resolve forward branch
32974 CODE THEN \ immediate
32975 MOV &DP,0(TOS) \ -- IFadr
32981 [UNDEFINED] ELSE [IF]
32982 \ https://forth-standard.org/standard/core/ELSE
32983 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
32984 CODE ELSE \ immediate
32985 ADD #4,&DP \ make room to compile two words
32986 MOV &DP,W \ W=HERE+4
32988 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
32990 MOV W,TOS \ -- ELSEadr
32995 [UNDEFINED] IS [IF] \ define DEFER! and IS
32997 \ https://forth-standard.org/standard/core/DEFERStore
32998 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
32999 CODE DEFER! \ xt2 xt1 --
33000 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
33005 \ https://forth-standard.org/standard/core/IS
33008 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
33009 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
33010 \ or in a definition : ... ['] U. IS DISPLAY ...
33011 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
33013 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
33017 IF POSTPONE ['] POSTPONE DEFER!
33023 [UNDEFINED] >BODY [IF]
33024 \ https://forth-standard.org/standard/core/toBODY
33025 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
33032 \ CODE 20uS \ n -- 8MHz version
33033 \ BEGIN \ 4 + 16 ~ loop
33034 \ MOV #39,rDOCON \ 39
33041 \ MOV #XDOCON,rDOCON \ 2
33046 CODE 20_US \ n -- n * 20 us
33047 BEGIN \ here we presume that LCD_TIM_IFG = 1...
33049 BIT #1,&LCD_TIM_CTL \ 3
33050 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
33051 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
33053 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
33058 CODE TOP_LCD \ LCD Sample
33059 \ \ if write : %xxxx_WWWW --
33060 \ \ if read : -- %0000_RRRR
33061 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33062 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33063 0= IF \ write LCD bits pattern
33064 AND.B #LCD_DB,TOS \
33065 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33066 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33069 THEN \ read LCD bits pattern
33072 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33073 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33074 AND.B #LCD_DB,TOS \
33078 CODE LCD_WRC \ char -- Write Char
33079 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33081 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
33082 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
33083 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33084 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33085 COLON \ high level word starts here
33086 TOP_LCD 2 20_US \ write high nibble first
33090 CODE LCD_WRF \ func -- Write Fonction
33091 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33095 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
33096 : LCD_HOME $02 LCD_WRF 100 20_us ;
33098 \ [UNDEFINED] OR [IF]
33100 \ \ https://forth-standard.org/standard/core/OR
33101 \ \ C OR x1 x2 -- x3 logical OR
33109 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
33110 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
33111 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
33112 \ : LCD_FN_SET $20 OR LCD_WrF ;
33113 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
33114 \ : LCD_GOTO $80 OR LCD_WrF ;
33117 \ CODE LCD_RDS \ -- status Read Status
33118 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33119 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33120 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33121 \ COLON \ starts a FORTH word
33122 \ TOP_LCD 2 20_us \ -- %0000_HHHH
33123 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
33124 \ HI2LO \ switch from FORTH to assembler
33125 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
33126 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
33127 \ MOV @RSP+,IP \ restore IP saved by COLON
33131 \ CODE LCD_RDC \ -- char Read Char
33132 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33137 \ ******************************\
33138 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33139 \ ******************************\
33140 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
33141 BIT.B #SW2,&SW2_IN \ test switch S2
33142 0= IF \ case of switch S2 pressed
33143 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
33145 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
33148 BIT.B #SW1,&SW1_IN \ test switch S1 input
33149 0= IF \ case of Switch S1 pressed
33150 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
33152 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
33159 \ ******************************\
33160 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
33161 \ ******************************\
33162 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33163 \ ******************************\
33164 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33165 \ \ SMclock = 8|16|24 MHz
33166 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
33167 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
33168 \ \ SR(9)=new Toggle bit memory (ADD on)
33169 \ ******************************\
33170 \ RC5_FirstStartBitHalfCycle: \
33171 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
33172 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
33173 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
33175 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
33176 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
33178 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
33179 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
33181 MOV #1778,X \ RC5_Period * 1us
33182 MOV #14,W \ count of loop
33184 \ ******************************\
33185 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
33186 \ ******************************\ |
33187 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
33188 \ RC5_Compute_3/4_Period: \ |
33189 RRUM #1,X \ X=1/2 cycle |
33192 ADD X,Y \ Y=3/4 cycle
33193 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
33195 \ ******************************\
33196 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
33197 \ ******************************\
33198 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33199 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
33200 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33201 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33202 SUB #1,W \ decrement count loop
33203 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
33204 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33205 0<> WHILE \ ----> out of loop ----+
33206 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
33208 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
33209 CMP Y,X \ 1 | cycle time out of bound ?
33210 U>= IF \ 2 ^ | yes:
33211 BIC #$30,&RC5_TIM_CTL \ | | stop timer
33212 GOTO FW1 \ | | quit on truncated RC5 message
33214 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
33216 REPEAT \ ----> loop back --+ | with X = new RC5_period value
33217 \ ******************************\ |
33218 \ RC5_SampleEndOf: \ <---------------------+
33219 \ ******************************\
33220 BIC #$30,&RC5_TIM_CTL \ stop timer
33221 \ ******************************\
33222 \ RC5_ComputeNewRC5word \
33223 \ ******************************\
33224 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
33225 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
33226 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
33227 \ ******************************\
33228 \ RC5_ComputeC6bit \
33229 \ ******************************\
33230 BIT #BIT14,T \ test /C6 bit in T
33231 0= IF BIS #BIT6,X \ set C6 bit in X
33232 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
33233 \ ******************************\
33234 \ RC5_CommandByteIsDone \ -- BASE RC5_code
33235 \ ******************************\
33236 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
33237 \ ******************************\
33238 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
33239 XOR @RSP,T \ (new XOR old) Toggle bits
33240 BIT #UF10,T \ repeated RC5_command ?
33241 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
33242 XOR #UF10,0(RSP) \ 5 toggle bit memory
33243 \ ******************************\
33244 \ Display IR_RC5 code \
33245 \ ******************************\
33246 SUB #8,PSP \ TOS -- x x x x TOS
33247 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
33248 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
33249 MOV #$10,&BASEADR \ set hexadecimal base
33250 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
33251 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
33252 LO2HI \ switch from assembler to FORTH
33253 LCD_CLEAR \ set LCD cursor at home
33254 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
33255 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
33256 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
33257 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
33258 HI2LO \ -- switch from FORTH to assembler
33259 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
33260 MOV @PSP+,TOS \ -- TOS
33262 MOV @RSP+,SR \ restore SR flags
33263 BIC #%1111_1000,SR \ but force CPU Active Mode
33264 RET \ (instead of RETI)
33268 \ ------------------------------\
33269 HDNCODE STOP_R2L \ define new STOP_APP
33270 \ ------------------------------\
33271 CMP #RET_ADR,&{RC5TOLCD}+8 \
33272 0<> IF \ if previous START executing
33273 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
33274 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
33275 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
33276 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
33277 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
33278 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
33279 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
33280 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
33281 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
33282 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
33287 \ ------------------------------\
33289 \ ------------------------------\
33290 BW1 \ <-- INI_R2L for some events
33292 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
33294 ." RC5toLCD is removed,"
33295 ." type START to restart"
33298 \ ------------------------------\
33300 \ ------------------------------\
33301 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
33302 \ ------------------------------\
33304 \ ------------------------------\
33305 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
33306 \ ------------------------------\
33307 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
33308 \ ------------------------------\
33309 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
33310 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
33312 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
33313 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
33315 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
33316 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
33317 \ CMP #4,TOS \ hardware RST
33318 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
33319 \ CMP #2,TOS \ Power_ON event
33320 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
33322 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
33324 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
33326 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
33327 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
33328 \ ------------------------------\
33329 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
33330 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33331 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33332 \ -- \ID input divider \ 10 = /4
33333 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
33334 \ - \TBCLR TimerB Clear
33337 \ -------------------------------\
33338 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33339 \ -- \CM Capture Mode
33344 \ --- \OUTMOD \ 011 = set/reset
33350 \ -------------------------------\
33352 \ -------------------------------\
33354 \ ------------------------------\
33355 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
33356 \ ------------------------------\
33357 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
33358 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
33359 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
33360 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
33362 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
33363 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
33365 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
33366 \ ------------------------------\
33367 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
33368 \ ------------------------------\
33369 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
33370 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
33371 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33372 \ ------------------------------\
33373 BIS.B #LCDVo,&LCDVo_DIR \
33374 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
33375 \ ------------------------------\
33376 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33377 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33378 \ ------------------------------\
33379 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33380 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33381 \ ******************************\
33383 \ ******************************\
33384 BIS.B #RC5,&IR_IE \ enable RC5_Int
33385 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33386 \ ******************************\
33387 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
33388 \ ******************************\
33389 \ %01 0001 0100 \ TAxCTL
33390 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
33391 \ -- \ ID divided by 1
33392 \ -- \ MC MODE = up to TAxCCRn
33393 \ - \ TACLR clear timer count
33396 \ ------------------------------\
33397 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
33398 \ ------------------------------\
33400 \ --- \ TAIDEX pre divisor
33401 \ ------------------------------\
33402 \ %0000 0000 0000 0101 \ TAxCCR0
33403 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
33404 \ ------------------------------\
33405 \ %0000 0000 0001 0000 \ TAxCCTL0
33406 \ - \ CAP capture/compare mode = compare
33409 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
33410 \ ------------------------------\
33411 \ define LPM mode for ACCEPT \
33412 \ ------------------------------\
33413 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
33414 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33415 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33416 \ ------------------------------\
33418 \ ------------------------------\
33420 \ ------------------------------\
33421 #1000 20_US \ 1- wait 20 ms
33422 %011 TOP_LCD \ 2- send DB5=DB4=1
33423 #205 20_US \ 3- wait 4,1 ms
33424 %011 TOP_LCD \ 4- send again DB5=DB4=1
33425 #5 20_US \ 5- wait 0,1 ms
33426 %011 TOP_LCD \ 6- send again again DB5=DB4=1
33427 #2 20_US \ wait 40 us = LCD cycle
33428 %010 TOP_LCD \ 7- send DB5=1 DB4=0
33429 #2 20_US \ wait 40 us = LCD cycle
33430 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33431 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33432 LCD_CLEAR \ 10- "LCD_Clear"
33433 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33434 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33435 LCD_CLEAR \ 10- "LCD_Clear"
33436 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33437 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33438 CR ." I love you" \ display message on LCD
33439 ['] CR >BODY IS CR \ CR executes its default value
33440 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
33441 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
33444 \ ------------------------------\
33446 \ ------------------------------\
33447 CODE START \ this routine replaces WARM and COLD default values by these of this application.
33448 \ ------------------------------\
33449 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
33450 0= IF \ if not done, customizes MARKER_DOES
33451 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
33452 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
33453 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
33454 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
33455 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
33456 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
33457 MOV #RC5_INT,&IR_VEC \ init interrupt vector
33458 MOV #INI_R2L,PC \ then execute new INI_APP, without return
33462 \ ------------------------------\
33465 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
33467 MARKER {RC5TOLCD} \ restore the state before MARKER definition
33468 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
33469 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
33470 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
33471 \ {RC5TOLCD}+14: make room to save previous IR_VEC
33473 [UNDEFINED] CONSTANT [IF]
33474 \ https://forth-standard.org/standard/core/CONSTANT
33475 \ CONSTANT <name> n -- define a Forth CONSTANT
33479 MOV TOS,-2(W) \ PFA = n
33486 [UNDEFINED] STATE [IF]
33487 \ https://forth-standard.org/standard/core/STATE
33488 \ STATE -- a-addr holds compiler state
33489 STATEADR CONSTANT STATE
33493 \ https://forth-standard.org/standard/core/Equal
33494 \ = x1 x2 -- flag test x1=x2
33501 XOR #-1,TOS \ 1 flag Z = 1
33506 [UNDEFINED] IF [IF] \ define IF and THEN
33507 \ https://forth-standard.org/standard/core/IF
33508 \ IF -- IFadr initialize conditional forward branch
33509 CODE IF \ immediate
33512 MOV &DP,TOS \ -- HERE
33513 ADD #4,&DP \ compile one word, reserve one word
33514 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
33515 ADD #2,TOS \ -- HERE+2=IFadr
33519 \ https://forth-standard.org/standard/core/THEN
33520 \ THEN IFadr -- resolve forward branch
33521 CODE THEN \ immediate
33522 MOV &DP,0(TOS) \ -- IFadr
33528 [UNDEFINED] ELSE [IF]
33529 \ https://forth-standard.org/standard/core/ELSE
33530 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
33531 CODE ELSE \ immediate
33532 ADD #4,&DP \ make room to compile two words
33533 MOV &DP,W \ W=HERE+4
33535 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
33537 MOV W,TOS \ -- ELSEadr
33542 [UNDEFINED] IS [IF] \ define DEFER! and IS
33544 \ https://forth-standard.org/standard/core/DEFERStore
33545 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
33546 CODE DEFER! \ xt2 xt1 --
33547 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
33552 \ https://forth-standard.org/standard/core/IS
33555 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
33556 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
33557 \ or in a definition : ... ['] U. IS DISPLAY ...
33558 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
33560 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
33564 IF POSTPONE ['] POSTPONE DEFER!
33570 [UNDEFINED] >BODY [IF]
33571 \ https://forth-standard.org/standard/core/toBODY
33572 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
33579 \ CODE 20uS \ n -- 8MHz version
33580 \ BEGIN \ 4 + 16 ~ loop
33581 \ MOV #39,rDOCON \ 39
33588 \ MOV #XDOCON,rDOCON \ 2
33593 CODE 20_US \ n -- n * 20 us
33594 BEGIN \ here we presume that LCD_TIM_IFG = 1...
33596 BIT #1,&LCD_TIM_CTL \ 3
33597 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
33598 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
33600 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
33605 CODE TOP_LCD \ LCD Sample
33606 \ \ if write : %xxxx_WWWW --
33607 \ \ if read : -- %0000_RRRR
33608 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33609 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33610 0= IF \ write LCD bits pattern
33611 AND.B #LCD_DB,TOS \
33612 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33613 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33616 THEN \ read LCD bits pattern
33619 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33620 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33621 AND.B #LCD_DB,TOS \
33625 CODE LCD_WRC \ char -- Write Char
33626 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33628 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
33629 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
33630 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33631 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33632 COLON \ high level word starts here
33633 TOP_LCD 2 20_US \ write high nibble first
33637 CODE LCD_WRF \ func -- Write Fonction
33638 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33642 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
33643 : LCD_HOME $02 LCD_WRF 100 20_us ;
33645 \ [UNDEFINED] OR [IF]
33647 \ \ https://forth-standard.org/standard/core/OR
33648 \ \ C OR x1 x2 -- x3 logical OR
33656 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
33657 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
33658 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
33659 \ : LCD_FN_SET $20 OR LCD_WrF ;
33660 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
33661 \ : LCD_GOTO $80 OR LCD_WrF ;
33664 \ CODE LCD_RDS \ -- status Read Status
33665 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33666 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33667 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33668 \ COLON \ starts a FORTH word
33669 \ TOP_LCD 2 20_us \ -- %0000_HHHH
33670 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
33671 \ HI2LO \ switch from FORTH to assembler
33672 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
33673 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
33674 \ MOV @RSP+,IP \ restore IP saved by COLON
33678 \ CODE LCD_RDC \ -- char Read Char
33679 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33684 \ ******************************\
33685 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33686 \ ******************************\
33687 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
33688 BIT.B #SW2,&SW2_IN \ test switch S2
33689 0= IF \ case of switch S2 pressed
33690 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
33692 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
33695 BIT.B #SW1,&SW1_IN \ test switch S1 input
33696 0= IF \ case of Switch S1 pressed
33697 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
33699 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
33706 \ ******************************\
33707 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
33708 \ ******************************\
33709 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33710 \ ******************************\
33711 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33712 \ \ SMclock = 8|16|24 MHz
33713 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
33714 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
33715 \ \ SR(9)=new Toggle bit memory (ADD on)
33716 \ ******************************\
33717 \ RC5_FirstStartBitHalfCycle: \
33718 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
33719 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
33720 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
33722 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
33723 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
33725 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
33726 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
33728 MOV #1778,X \ RC5_Period * 1us
33729 MOV #14,W \ count of loop
33731 \ ******************************\
33732 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
33733 \ ******************************\ |
33734 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
33735 \ RC5_Compute_3/4_Period: \ |
33736 RRUM #1,X \ X=1/2 cycle |
33739 ADD X,Y \ Y=3/4 cycle
33740 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
33742 \ ******************************\
33743 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
33744 \ ******************************\
33745 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33746 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
33747 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33748 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33749 SUB #1,W \ decrement count loop
33750 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
33751 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33752 0<> WHILE \ ----> out of loop ----+
33753 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
33755 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
33756 CMP Y,X \ 1 | cycle time out of bound ?
33757 U>= IF \ 2 ^ | yes:
33758 BIC #$30,&RC5_TIM_CTL \ | | stop timer
33759 GOTO FW1 \ | | quit on truncated RC5 message
33761 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
33763 REPEAT \ ----> loop back --+ | with X = new RC5_period value
33764 \ ******************************\ |
33765 \ RC5_SampleEndOf: \ <---------------------+
33766 \ ******************************\
33767 BIC #$30,&RC5_TIM_CTL \ stop timer
33768 \ ******************************\
33769 \ RC5_ComputeNewRC5word \
33770 \ ******************************\
33771 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
33772 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
33773 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
33774 \ ******************************\
33775 \ RC5_ComputeC6bit \
33776 \ ******************************\
33777 BIT #BIT14,T \ test /C6 bit in T
33778 0= IF BIS #BIT6,X \ set C6 bit in X
33779 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
33780 \ ******************************\
33781 \ RC5_CommandByteIsDone \ -- BASE RC5_code
33782 \ ******************************\
33783 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
33784 \ ******************************\
33785 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
33786 XOR @RSP,T \ (new XOR old) Toggle bits
33787 BIT #UF10,T \ repeated RC5_command ?
33788 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
33789 XOR #UF10,0(RSP) \ 5 toggle bit memory
33790 \ ******************************\
33791 \ Display IR_RC5 code \
33792 \ ******************************\
33793 SUB #8,PSP \ TOS -- x x x x TOS
33794 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
33795 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
33796 MOV #$10,&BASEADR \ set hexadecimal base
33797 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
33798 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
33799 LO2HI \ switch from assembler to FORTH
33800 LCD_CLEAR \ set LCD cursor at home
33801 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
33802 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
33803 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
33804 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
33805 HI2LO \ -- switch from FORTH to assembler
33806 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
33807 MOV @PSP+,TOS \ -- TOS
33809 MOV @RSP+,SR \ restore SR flags
33810 BIC #%1111_1000,SR \ but force CPU Active Mode
33811 RET \ (instead of RETI)
33815 \ ------------------------------\
33816 HDNCODE STOP_R2L \ define new STOP_APP
33817 \ ------------------------------\
33818 CMP #RET_ADR,&{RC5TOLCD}+8 \
33819 0<> IF \ if previous START executing
33820 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
33821 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
33822 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
33823 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
33824 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
33825 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
33826 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
33827 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
33828 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
33829 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
33834 \ ------------------------------\
33836 \ ------------------------------\
33837 BW1 \ <-- INI_R2L for some events
33839 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
33841 ." RC5toLCD is removed,"
33842 ." type START to restart"
33845 \ ------------------------------\
33847 \ ------------------------------\
33848 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
33849 \ ------------------------------\
33851 \ ------------------------------\
33852 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
33853 \ ------------------------------\
33854 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
33855 \ ------------------------------\
33856 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
33857 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
33859 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
33860 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
33862 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
33863 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
33864 \ CMP #4,TOS \ hardware RST
33865 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
33866 \ CMP #2,TOS \ Power_ON event
33867 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
33869 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
33871 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
33873 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
33874 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
33875 \ ------------------------------\
33876 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
33877 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33878 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33879 \ -- \ID input divider \ 10 = /4
33880 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
33881 \ - \TBCLR TimerB Clear
33884 \ -------------------------------\
33885 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33886 \ -- \CM Capture Mode
33891 \ --- \OUTMOD \ 011 = set/reset
33897 \ -------------------------------\
33899 \ -------------------------------\
33901 \ ------------------------------\
33902 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
33903 \ ------------------------------\
33904 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
33905 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
33906 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
33907 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
33909 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
33910 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
33912 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
33913 \ ------------------------------\
33914 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
33915 \ ------------------------------\
33916 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
33917 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
33918 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33919 \ ------------------------------\
33920 BIS.B #LCDVo,&LCDVo_DIR \
33921 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
33922 \ ------------------------------\
33923 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33924 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33925 \ ------------------------------\
33926 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33927 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33928 \ ******************************\
33930 \ ******************************\
33931 BIS.B #RC5,&IR_IE \ enable RC5_Int
33932 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33933 \ ******************************\
33934 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
33935 \ ******************************\
33936 \ %01 0001 0100 \ TAxCTL
33937 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
33938 \ -- \ ID divided by 1
33939 \ -- \ MC MODE = up to TAxCCRn
33940 \ - \ TACLR clear timer count
33943 \ ------------------------------\
33944 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
33945 \ ------------------------------\
33947 \ --- \ TAIDEX pre divisor
33948 \ ------------------------------\
33949 \ %0000 0000 0000 0101 \ TAxCCR0
33950 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
33951 \ ------------------------------\
33952 \ %0000 0000 0001 0000 \ TAxCCTL0
33953 \ - \ CAP capture/compare mode = compare
33956 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
33957 \ ------------------------------\
33958 \ define LPM mode for ACCEPT \
33959 \ ------------------------------\
33960 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
33961 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33962 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33963 \ ------------------------------\
33965 \ ------------------------------\
33967 \ ------------------------------\
33968 #1000 20_US \ 1- wait 20 ms
33969 %011 TOP_LCD \ 2- send DB5=DB4=1
33970 #205 20_US \ 3- wait 4,1 ms
33971 %011 TOP_LCD \ 4- send again DB5=DB4=1
33972 #5 20_US \ 5- wait 0,1 ms
33973 %011 TOP_LCD \ 6- send again again DB5=DB4=1
33974 #2 20_US \ wait 40 us = LCD cycle
33975 %010 TOP_LCD \ 7- send DB5=1 DB4=0
33976 #2 20_US \ wait 40 us = LCD cycle
33977 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33978 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33979 LCD_CLEAR \ 10- "LCD_Clear"
33980 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33981 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33982 LCD_CLEAR \ 10- "LCD_Clear"
33983 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33984 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33985 CR ." I love you" \ display message on LCD
33986 ['] CR >BODY IS CR \ CR executes its default value
33987 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
33988 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
33991 \ ------------------------------\
33993 \ ------------------------------\
33994 CODE START \ this routine replaces WARM and COLD default values by these of this application.
33995 \ ------------------------------\
33996 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
33997 0= IF \ if not done, customizes MARKER_DOES
33998 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
33999 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
34000 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
34001 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
34002 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
34003 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
34004 MOV #RC5_INT,&IR_VEC \ init interrupt vector
34005 MOV #INI_R2L,PC \ then execute new INI_APP, without return
34009 \ ------------------------------\
34012 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
34014 MARKER {RC5TOLCD} \ restore the state before MARKER definition
34015 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
34016 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
34017 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
34018 \ {RC5TOLCD}+14: make room to save previous IR_VEC
34020 [UNDEFINED] CONSTANT [IF]
34021 \ https://forth-standard.org/standard/core/CONSTANT
34022 \ CONSTANT <name> n -- define a Forth CONSTANT
34026 MOV TOS,-2(W) \ PFA = n
34033 [UNDEFINED] STATE [IF]
34034 \ https://forth-standard.org/standard/core/STATE
34035 \ STATE -- a-addr holds compiler state
34036 STATEADR CONSTANT STATE
34040 \ https://forth-standard.org/standard/core/Equal
34041 \ = x1 x2 -- flag test x1=x2
34048 XOR #-1,TOS \ 1 flag Z = 1
34053 [UNDEFINED] IF [IF] \ define IF and THEN
34054 \ https://forth-standard.org/standard/core/IF
34055 \ IF -- IFadr initialize conditional forward branch
34056 CODE IF \ immediate
34059 MOV &DP,TOS \ -- HERE
34060 ADD #4,&DP \ compile one word, reserve one word
34061 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
34062 ADD #2,TOS \ -- HERE+2=IFadr
34066 \ https://forth-standard.org/standard/core/THEN
34067 \ THEN IFadr -- resolve forward branch
34068 CODE THEN \ immediate
34069 MOV &DP,0(TOS) \ -- IFadr
34075 [UNDEFINED] ELSE [IF]
34076 \ https://forth-standard.org/standard/core/ELSE
34077 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
34078 CODE ELSE \ immediate
34079 ADD #4,&DP \ make room to compile two words
34080 MOV &DP,W \ W=HERE+4
34082 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
34084 MOV W,TOS \ -- ELSEadr
34089 [UNDEFINED] IS [IF] \ define DEFER! and IS
34091 \ https://forth-standard.org/standard/core/DEFERStore
34092 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
34093 CODE DEFER! \ xt2 xt1 --
34094 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
34099 \ https://forth-standard.org/standard/core/IS
34102 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
34103 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
34104 \ or in a definition : ... ['] U. IS DISPLAY ...
34105 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
34107 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
34111 IF POSTPONE ['] POSTPONE DEFER!
34117 [UNDEFINED] >BODY [IF]
34118 \ https://forth-standard.org/standard/core/toBODY
34119 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
34126 \ CODE 20uS \ n -- 8MHz version
34127 \ BEGIN \ 4 + 16 ~ loop
34128 \ MOV #39,rDOCON \ 39
34135 \ MOV #XDOCON,rDOCON \ 2
34140 CODE 20_US \ n -- n * 20 us
34141 BEGIN \ here we presume that LCD_TIM_IFG = 1...
34143 BIT #1,&LCD_TIM_CTL \ 3
34144 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
34145 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
34147 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
34152 CODE TOP_LCD \ LCD Sample
34153 \ \ if write : %xxxx_WWWW --
34154 \ \ if read : -- %0000_RRRR
34155 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34156 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34157 0= IF \ write LCD bits pattern
34158 AND.B #LCD_DB,TOS \
34159 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34160 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34163 THEN \ read LCD bits pattern
34166 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34167 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34168 AND.B #LCD_DB,TOS \
34172 CODE LCD_WRC \ char -- Write Char
34173 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34175 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
34176 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
34177 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34178 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34179 COLON \ high level word starts here
34180 TOP_LCD 2 20_US \ write high nibble first
34184 CODE LCD_WRF \ func -- Write Fonction
34185 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34189 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
34190 : LCD_HOME $02 LCD_WRF 100 20_us ;
34192 \ [UNDEFINED] OR [IF]
34194 \ \ https://forth-standard.org/standard/core/OR
34195 \ \ C OR x1 x2 -- x3 logical OR
34203 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
34204 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
34205 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
34206 \ : LCD_FN_SET $20 OR LCD_WrF ;
34207 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
34208 \ : LCD_GOTO $80 OR LCD_WrF ;
34211 \ CODE LCD_RDS \ -- status Read Status
34212 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34213 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34214 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34215 \ COLON \ starts a FORTH word
34216 \ TOP_LCD 2 20_us \ -- %0000_HHHH
34217 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
34218 \ HI2LO \ switch from FORTH to assembler
34219 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
34220 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
34221 \ MOV @RSP+,IP \ restore IP saved by COLON
34225 \ CODE LCD_RDC \ -- char Read Char
34226 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34231 \ ******************************\
34232 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34233 \ ******************************\
34234 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
34235 BIT.B #SW2,&SW2_IN \ test switch S2
34236 0= IF \ case of switch S2 pressed
34237 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
34239 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
34242 BIT.B #SW1,&SW1_IN \ test switch S1 input
34243 0= IF \ case of Switch S1 pressed
34244 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
34246 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
34253 \ ******************************\
34254 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
34255 \ ******************************\
34256 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34257 \ ******************************\
34258 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34259 \ \ SMclock = 8|16|24 MHz
34260 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
34261 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
34262 \ \ SR(9)=new Toggle bit memory (ADD on)
34263 \ ******************************\
34264 \ RC5_FirstStartBitHalfCycle: \
34265 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
34266 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
34267 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
34269 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
34270 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
34272 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
34273 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
34275 MOV #1778,X \ RC5_Period * 1us
34276 MOV #14,W \ count of loop
34278 \ ******************************\
34279 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
34280 \ ******************************\ |
34281 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
34282 \ RC5_Compute_3/4_Period: \ |
34283 RRUM #1,X \ X=1/2 cycle |
34286 ADD X,Y \ Y=3/4 cycle
34287 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
34289 \ ******************************\
34290 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
34291 \ ******************************\
34292 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34293 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
34294 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34295 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34296 SUB #1,W \ decrement count loop
34297 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
34298 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34299 0<> WHILE \ ----> out of loop ----+
34300 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
34302 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
34303 CMP Y,X \ 1 | cycle time out of bound ?
34304 U>= IF \ 2 ^ | yes:
34305 BIC #$30,&RC5_TIM_CTL \ | | stop timer
34306 GOTO FW1 \ | | quit on truncated RC5 message
34308 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
34310 REPEAT \ ----> loop back --+ | with X = new RC5_period value
34311 \ ******************************\ |
34312 \ RC5_SampleEndOf: \ <---------------------+
34313 \ ******************************\
34314 BIC #$30,&RC5_TIM_CTL \ stop timer
34315 \ ******************************\
34316 \ RC5_ComputeNewRC5word \
34317 \ ******************************\
34318 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
34319 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
34320 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
34321 \ ******************************\
34322 \ RC5_ComputeC6bit \
34323 \ ******************************\
34324 BIT #BIT14,T \ test /C6 bit in T
34325 0= IF BIS #BIT6,X \ set C6 bit in X
34326 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
34327 \ ******************************\
34328 \ RC5_CommandByteIsDone \ -- BASE RC5_code
34329 \ ******************************\
34330 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
34331 \ ******************************\
34332 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
34333 XOR @RSP,T \ (new XOR old) Toggle bits
34334 BIT #UF10,T \ repeated RC5_command ?
34335 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
34336 XOR #UF10,0(RSP) \ 5 toggle bit memory
34337 \ ******************************\
34338 \ Display IR_RC5 code \
34339 \ ******************************\
34340 SUB #8,PSP \ TOS -- x x x x TOS
34341 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
34342 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
34343 MOV #$10,&BASEADR \ set hexadecimal base
34344 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
34345 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
34346 LO2HI \ switch from assembler to FORTH
34347 LCD_CLEAR \ set LCD cursor at home
34348 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
34349 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
34350 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
34351 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
34352 HI2LO \ -- switch from FORTH to assembler
34353 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
34354 MOV @PSP+,TOS \ -- TOS
34356 MOV @RSP+,SR \ restore SR flags
34357 BIC #%1111_1000,SR \ but force CPU Active Mode
34358 RET \ (instead of RETI)
34362 \ ------------------------------\
34363 HDNCODE STOP_R2L \ define new STOP_APP
34364 \ ------------------------------\
34365 CMP #RET_ADR,&{RC5TOLCD}+8 \
34366 0<> IF \ if previous START executing
34367 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
34368 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
34369 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
34370 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
34371 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
34372 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
34373 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
34374 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
34375 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
34376 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
34381 \ ------------------------------\
34383 \ ------------------------------\
34384 BW1 \ <-- INI_R2L for some events
34386 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
34388 ." RC5toLCD is removed,"
34389 ." type START to restart"
34392 \ ------------------------------\
34394 \ ------------------------------\
34395 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
34396 \ ------------------------------\
34398 \ ------------------------------\
34399 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
34400 \ ------------------------------\
34401 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
34402 \ ------------------------------\
34403 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
34404 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
34406 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
34407 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
34409 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
34410 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
34411 \ CMP #4,TOS \ hardware RST
34412 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
34413 \ CMP #2,TOS \ Power_ON event
34414 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
34416 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
34418 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
34420 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
34421 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
34422 \ ------------------------------\
34423 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
34424 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34425 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34426 \ -- \ID input divider \ 10 = /4
34427 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
34428 \ - \TBCLR TimerB Clear
34431 \ -------------------------------\
34432 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34433 \ -- \CM Capture Mode
34438 \ --- \OUTMOD \ 011 = set/reset
34444 \ -------------------------------\
34446 \ -------------------------------\
34448 \ ------------------------------\
34449 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
34450 \ ------------------------------\
34451 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
34452 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
34453 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
34454 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
34456 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
34457 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
34459 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
34460 \ ------------------------------\
34461 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
34462 \ ------------------------------\
34463 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
34464 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
34465 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34466 \ ------------------------------\
34467 BIS.B #LCDVo,&LCDVo_DIR \
34468 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
34469 \ ------------------------------\
34470 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34471 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34472 \ ------------------------------\
34473 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
34474 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
34475 \ ******************************\
34477 \ ******************************\
34478 BIS.B #RC5,&IR_IE \ enable RC5_Int
34479 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
34480 \ ******************************\
34481 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
34482 \ ******************************\
34483 \ %01 0001 0100 \ TAxCTL
34484 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
34485 \ -- \ ID divided by 1
34486 \ -- \ MC MODE = up to TAxCCRn
34487 \ - \ TACLR clear timer count
34490 \ ------------------------------\
34491 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
34492 \ ------------------------------\
34494 \ --- \ TAIDEX pre divisor
34495 \ ------------------------------\
34496 \ %0000 0000 0000 0101 \ TAxCCR0
34497 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
34498 \ ------------------------------\
34499 \ %0000 0000 0001 0000 \ TAxCCTL0
34500 \ - \ CAP capture/compare mode = compare
34503 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
34504 \ ------------------------------\
34505 \ define LPM mode for ACCEPT \
34506 \ ------------------------------\
34507 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
34508 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34509 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34510 \ ------------------------------\
34512 \ ------------------------------\
34514 \ ------------------------------\
34515 #1000 20_US \ 1- wait 20 ms
34516 %011 TOP_LCD \ 2- send DB5=DB4=1
34517 #205 20_US \ 3- wait 4,1 ms
34518 %011 TOP_LCD \ 4- send again DB5=DB4=1
34519 #5 20_US \ 5- wait 0,1 ms
34520 %011 TOP_LCD \ 6- send again again DB5=DB4=1
34521 #2 20_US \ wait 40 us = LCD cycle
34522 %010 TOP_LCD \ 7- send DB5=1 DB4=0
34523 #2 20_US \ wait 40 us = LCD cycle
34524 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34525 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34526 LCD_CLEAR \ 10- "LCD_Clear"
34527 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34528 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34529 LCD_CLEAR \ 10- "LCD_Clear"
34530 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34531 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34532 CR ." I love you" \ display message on LCD
34533 ['] CR >BODY IS CR \ CR executes its default value
34534 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
34535 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
34538 \ ------------------------------\
34540 \ ------------------------------\
34541 CODE START \ this routine replaces WARM and COLD default values by these of this application.
34542 \ ------------------------------\
34543 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
34544 0= IF \ if not done, customizes MARKER_DOES
34545 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
34546 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
34547 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
34548 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
34549 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
34550 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
34551 MOV #RC5_INT,&IR_VEC \ init interrupt vector
34552 MOV #INI_R2L,PC \ then execute new INI_APP, without return
34556 \ ------------------------------\
34559 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
34561 MARKER {RC5TOLCD} \ restore the state before MARKER definition
34562 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
34563 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
34564 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
34565 \ {RC5TOLCD}+14: make room to save previous IR_VEC
34567 [UNDEFINED] CONSTANT [IF]
34568 \ https://forth-standard.org/standard/core/CONSTANT
34569 \ CONSTANT <name> n -- define a Forth CONSTANT
34573 MOV TOS,-2(W) \ PFA = n
34580 [UNDEFINED] STATE [IF]
34581 \ https://forth-standard.org/standard/core/STATE
34582 \ STATE -- a-addr holds compiler state
34583 STATEADR CONSTANT STATE
34587 \ https://forth-standard.org/standard/core/Equal
34588 \ = x1 x2 -- flag test x1=x2
34595 XOR #-1,TOS \ 1 flag Z = 1
34600 [UNDEFINED] IF [IF] \ define IF and THEN
34601 \ https://forth-standard.org/standard/core/IF
34602 \ IF -- IFadr initialize conditional forward branch
34603 CODE IF \ immediate
34606 MOV &DP,TOS \ -- HERE
34607 ADD #4,&DP \ compile one word, reserve one word
34608 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
34609 ADD #2,TOS \ -- HERE+2=IFadr
34613 \ https://forth-standard.org/standard/core/THEN
34614 \ THEN IFadr -- resolve forward branch
34615 CODE THEN \ immediate
34616 MOV &DP,0(TOS) \ -- IFadr
34622 [UNDEFINED] ELSE [IF]
34623 \ https://forth-standard.org/standard/core/ELSE
34624 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
34625 CODE ELSE \ immediate
34626 ADD #4,&DP \ make room to compile two words
34627 MOV &DP,W \ W=HERE+4
34629 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
34631 MOV W,TOS \ -- ELSEadr
34636 [UNDEFINED] IS [IF] \ define DEFER! and IS
34638 \ https://forth-standard.org/standard/core/DEFERStore
34639 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
34640 CODE DEFER! \ xt2 xt1 --
34641 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
34646 \ https://forth-standard.org/standard/core/IS
34649 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
34650 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
34651 \ or in a definition : ... ['] U. IS DISPLAY ...
34652 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
34654 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
34658 IF POSTPONE ['] POSTPONE DEFER!
34664 [UNDEFINED] >BODY [IF]
34665 \ https://forth-standard.org/standard/core/toBODY
34666 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
34673 \ CODE 20uS \ n -- 8MHz version
34674 \ BEGIN \ 4 + 16 ~ loop
34675 \ MOV #39,rDOCON \ 39
34682 \ MOV #XDOCON,rDOCON \ 2
34687 CODE 20_US \ n -- n * 20 us
34688 BEGIN \ here we presume that LCD_TIM_IFG = 1...
34690 BIT #1,&LCD_TIM_CTL \ 3
34691 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
34692 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
34694 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
34699 CODE TOP_LCD \ LCD Sample
34700 \ \ if write : %xxxx_WWWW --
34701 \ \ if read : -- %0000_RRRR
34702 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34703 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34704 0= IF \ write LCD bits pattern
34705 AND.B #LCD_DB,TOS \
34706 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34707 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34710 THEN \ read LCD bits pattern
34713 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34714 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34715 AND.B #LCD_DB,TOS \
34719 CODE LCD_WRC \ char -- Write Char
34720 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34722 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
34723 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
34724 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34725 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34726 COLON \ high level word starts here
34727 TOP_LCD 2 20_US \ write high nibble first
34731 CODE LCD_WRF \ func -- Write Fonction
34732 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34736 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
34737 : LCD_HOME $02 LCD_WRF 100 20_us ;
34739 \ [UNDEFINED] OR [IF]
34741 \ \ https://forth-standard.org/standard/core/OR
34742 \ \ C OR x1 x2 -- x3 logical OR
34750 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
34751 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
34752 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
34753 \ : LCD_FN_SET $20 OR LCD_WrF ;
34754 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
34755 \ : LCD_GOTO $80 OR LCD_WrF ;
34758 \ CODE LCD_RDS \ -- status Read Status
34759 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34760 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34761 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34762 \ COLON \ starts a FORTH word
34763 \ TOP_LCD 2 20_us \ -- %0000_HHHH
34764 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
34765 \ HI2LO \ switch from FORTH to assembler
34766 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
34767 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
34768 \ MOV @RSP+,IP \ restore IP saved by COLON
34772 \ CODE LCD_RDC \ -- char Read Char
34773 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34778 \ ******************************\
34779 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34780 \ ******************************\
34781 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
34782 BIT.B #SW2,&SW2_IN \ test switch S2
34783 0= IF \ case of switch S2 pressed
34784 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
34786 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
34789 BIT.B #SW1,&SW1_IN \ test switch S1 input
34790 0= IF \ case of Switch S1 pressed
34791 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
34793 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
34800 \ ******************************\
34801 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
34802 \ ******************************\
34803 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34804 \ ******************************\
34805 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34806 \ \ SMclock = 8|16|24 MHz
34807 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
34808 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
34809 \ \ SR(9)=new Toggle bit memory (ADD on)
34810 \ ******************************\
34811 \ RC5_FirstStartBitHalfCycle: \
34812 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
34813 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
34814 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
34816 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
34817 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
34819 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
34820 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
34822 MOV #1778,X \ RC5_Period * 1us
34823 MOV #14,W \ count of loop
34825 \ ******************************\
34826 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
34827 \ ******************************\ |
34828 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
34829 \ RC5_Compute_3/4_Period: \ |
34830 RRUM #1,X \ X=1/2 cycle |
34833 ADD X,Y \ Y=3/4 cycle
34834 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
34836 \ ******************************\
34837 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
34838 \ ******************************\
34839 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34840 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
34841 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34842 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34843 SUB #1,W \ decrement count loop
34844 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
34845 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34846 0<> WHILE \ ----> out of loop ----+
34847 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
34849 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
34850 CMP Y,X \ 1 | cycle time out of bound ?
34851 U>= IF \ 2 ^ | yes:
34852 BIC #$30,&RC5_TIM_CTL \ | | stop timer
34853 GOTO FW1 \ | | quit on truncated RC5 message
34855 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
34857 REPEAT \ ----> loop back --+ | with X = new RC5_period value
34858 \ ******************************\ |
34859 \ RC5_SampleEndOf: \ <---------------------+
34860 \ ******************************\
34861 BIC #$30,&RC5_TIM_CTL \ stop timer
34862 \ ******************************\
34863 \ RC5_ComputeNewRC5word \
34864 \ ******************************\
34865 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
34866 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
34867 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
34868 \ ******************************\
34869 \ RC5_ComputeC6bit \
34870 \ ******************************\
34871 BIT #BIT14,T \ test /C6 bit in T
34872 0= IF BIS #BIT6,X \ set C6 bit in X
34873 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
34874 \ ******************************\
34875 \ RC5_CommandByteIsDone \ -- BASE RC5_code
34876 \ ******************************\
34877 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
34878 \ ******************************\
34879 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
34880 XOR @RSP,T \ (new XOR old) Toggle bits
34881 BIT #UF10,T \ repeated RC5_command ?
34882 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
34883 XOR #UF10,0(RSP) \ 5 toggle bit memory
34884 \ ******************************\
34885 \ Display IR_RC5 code \
34886 \ ******************************\
34887 SUB #8,PSP \ TOS -- x x x x TOS
34888 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
34889 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
34890 MOV #$10,&BASEADR \ set hexadecimal base
34891 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
34892 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
34893 LO2HI \ switch from assembler to FORTH
34894 LCD_CLEAR \ set LCD cursor at home
34895 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
34896 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
34897 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
34898 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
34899 HI2LO \ -- switch from FORTH to assembler
34900 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
34901 MOV @PSP+,TOS \ -- TOS
34903 MOV @RSP+,SR \ restore SR flags
34904 BIC #%1111_1000,SR \ but force CPU Active Mode
34905 RET \ (instead of RETI)
34909 \ ------------------------------\
34910 HDNCODE STOP_R2L \ define new STOP_APP
34911 \ ------------------------------\
34912 CMP #RET_ADR,&{RC5TOLCD}+8 \
34913 0<> IF \ if previous START executing
34914 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
34915 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
34916 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
34917 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
34918 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
34919 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
34920 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
34921 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
34922 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
34923 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
34928 \ ------------------------------\
34930 \ ------------------------------\
34931 BW1 \ <-- INI_R2L for some events
34933 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
34935 ." RC5toLCD is removed,"
34936 ." type START to restart"
34939 \ ------------------------------\
34941 \ ------------------------------\
34942 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
34943 \ ------------------------------\
34945 \ ------------------------------\
34946 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
34947 \ ------------------------------\
34948 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
34949 \ ------------------------------\
34950 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
34951 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
34953 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
34954 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
34956 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
34957 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
34958 \ CMP #4,TOS \ hardware RST
34959 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
34960 \ CMP #2,TOS \ Power_ON event
34961 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
34963 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
34965 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
34967 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
34968 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
34969 \ ------------------------------\
34970 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
34971 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34972 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34973 \ -- \ID input divider \ 10 = /4
34974 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
34975 \ - \TBCLR TimerB Clear
34978 \ -------------------------------\
34979 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34980 \ -- \CM Capture Mode
34985 \ --- \OUTMOD \ 011 = set/reset
34991 \ -------------------------------\
34993 \ -------------------------------\
34995 \ ------------------------------\
34996 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
34997 \ ------------------------------\
34998 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
34999 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
35000 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
35001 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
35003 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
35004 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
35006 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
35007 \ ------------------------------\
35008 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
35009 \ ------------------------------\
35010 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
35011 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
35012 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35013 \ ------------------------------\
35014 BIS.B #LCDVo,&LCDVo_DIR \
35015 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
35016 \ ------------------------------\
35017 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35018 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35019 \ ------------------------------\
35020 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35021 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35022 \ ******************************\
35024 \ ******************************\
35025 BIS.B #RC5,&IR_IE \ enable RC5_Int
35026 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35027 \ ******************************\
35028 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
35029 \ ******************************\
35030 \ %01 0001 0100 \ TAxCTL
35031 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
35032 \ -- \ ID divided by 1
35033 \ -- \ MC MODE = up to TAxCCRn
35034 \ - \ TACLR clear timer count
35037 \ ------------------------------\
35038 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
35039 \ ------------------------------\
35041 \ --- \ TAIDEX pre divisor
35042 \ ------------------------------\
35043 \ %0000 0000 0000 0101 \ TAxCCR0
35044 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
35045 \ ------------------------------\
35046 \ %0000 0000 0001 0000 \ TAxCCTL0
35047 \ - \ CAP capture/compare mode = compare
35050 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
35051 \ ------------------------------\
35052 \ define LPM mode for ACCEPT \
35053 \ ------------------------------\
35054 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
35055 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35056 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35057 \ ------------------------------\
35059 \ ------------------------------\
35061 \ ------------------------------\
35062 #1000 20_US \ 1- wait 20 ms
35063 %011 TOP_LCD \ 2- send DB5=DB4=1
35064 #205 20_US \ 3- wait 4,1 ms
35065 %011 TOP_LCD \ 4- send again DB5=DB4=1
35066 #5 20_US \ 5- wait 0,1 ms
35067 %011 TOP_LCD \ 6- send again again DB5=DB4=1
35068 #2 20_US \ wait 40 us = LCD cycle
35069 %010 TOP_LCD \ 7- send DB5=1 DB4=0
35070 #2 20_US \ wait 40 us = LCD cycle
35071 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35072 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35073 LCD_CLEAR \ 10- "LCD_Clear"
35074 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35075 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35076 LCD_CLEAR \ 10- "LCD_Clear"
35077 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35078 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35079 CR ." I love you" \ display message on LCD
35080 ['] CR >BODY IS CR \ CR executes its default value
35081 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
35082 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
35085 \ ------------------------------\
35087 \ ------------------------------\
35088 CODE START \ this routine replaces WARM and COLD default values by these of this application.
35089 \ ------------------------------\
35090 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
35091 0= IF \ if not done, customizes MARKER_DOES
35092 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
35093 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
35094 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
35095 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
35096 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
35097 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
35098 MOV #RC5_INT,&IR_VEC \ init interrupt vector
35099 MOV #INI_R2L,PC \ then execute new INI_APP, without return
35103 \ ------------------------------\
35106 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
35108 MARKER {RC5TOLCD} \ restore the state before MARKER definition
35109 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
35110 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
35111 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
35112 \ {RC5TOLCD}+14: make room to save previous IR_VEC
35114 [UNDEFINED] CONSTANT [IF]
35115 \ https://forth-standard.org/standard/core/CONSTANT
35116 \ CONSTANT <name> n -- define a Forth CONSTANT
35120 MOV TOS,-2(W) \ PFA = n
35127 [UNDEFINED] STATE [IF]
35128 \ https://forth-standard.org/standard/core/STATE
35129 \ STATE -- a-addr holds compiler state
35130 STATEADR CONSTANT STATE
35134 \ https://forth-standard.org/standard/core/Equal
35135 \ = x1 x2 -- flag test x1=x2
35142 XOR #-1,TOS \ 1 flag Z = 1
35147 [UNDEFINED] IF [IF] \ define IF and THEN
35148 \ https://forth-standard.org/standard/core/IF
35149 \ IF -- IFadr initialize conditional forward branch
35150 CODE IF \ immediate
35153 MOV &DP,TOS \ -- HERE
35154 ADD #4,&DP \ compile one word, reserve one word
35155 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
35156 ADD #2,TOS \ -- HERE+2=IFadr
35160 \ https://forth-standard.org/standard/core/THEN
35161 \ THEN IFadr -- resolve forward branch
35162 CODE THEN \ immediate
35163 MOV &DP,0(TOS) \ -- IFadr
35169 [UNDEFINED] ELSE [IF]
35170 \ https://forth-standard.org/standard/core/ELSE
35171 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
35172 CODE ELSE \ immediate
35173 ADD #4,&DP \ make room to compile two words
35174 MOV &DP,W \ W=HERE+4
35176 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
35178 MOV W,TOS \ -- ELSEadr
35183 [UNDEFINED] IS [IF] \ define DEFER! and IS
35185 \ https://forth-standard.org/standard/core/DEFERStore
35186 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
35187 CODE DEFER! \ xt2 xt1 --
35188 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
35193 \ https://forth-standard.org/standard/core/IS
35196 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
35197 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
35198 \ or in a definition : ... ['] U. IS DISPLAY ...
35199 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
35201 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
35205 IF POSTPONE ['] POSTPONE DEFER!
35211 [UNDEFINED] >BODY [IF]
35212 \ https://forth-standard.org/standard/core/toBODY
35213 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
35220 \ CODE 20uS \ n -- 8MHz version
35221 \ BEGIN \ 4 + 16 ~ loop
35222 \ MOV #39,rDOCON \ 39
35229 \ MOV #XDOCON,rDOCON \ 2
35234 CODE 20_US \ n -- n * 20 us
35235 BEGIN \ here we presume that LCD_TIM_IFG = 1...
35237 BIT #1,&LCD_TIM_CTL \ 3
35238 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
35239 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
35241 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
35246 CODE TOP_LCD \ LCD Sample
35247 \ \ if write : %xxxx_WWWW --
35248 \ \ if read : -- %0000_RRRR
35249 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35250 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35251 0= IF \ write LCD bits pattern
35252 AND.B #LCD_DB,TOS \
35253 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35254 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35257 THEN \ read LCD bits pattern
35260 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35261 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35262 AND.B #LCD_DB,TOS \
35266 CODE LCD_WRC \ char -- Write Char
35267 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35269 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
35270 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
35271 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35272 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35273 COLON \ high level word starts here
35274 TOP_LCD 2 20_US \ write high nibble first
35278 CODE LCD_WRF \ func -- Write Fonction
35279 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35283 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
35284 : LCD_HOME $02 LCD_WRF 100 20_us ;
35286 \ [UNDEFINED] OR [IF]
35288 \ \ https://forth-standard.org/standard/core/OR
35289 \ \ C OR x1 x2 -- x3 logical OR
35297 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
35298 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
35299 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
35300 \ : LCD_FN_SET $20 OR LCD_WrF ;
35301 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
35302 \ : LCD_GOTO $80 OR LCD_WrF ;
35305 \ CODE LCD_RDS \ -- status Read Status
35306 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35307 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35308 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35309 \ COLON \ starts a FORTH word
35310 \ TOP_LCD 2 20_us \ -- %0000_HHHH
35311 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
35312 \ HI2LO \ switch from FORTH to assembler
35313 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
35314 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
35315 \ MOV @RSP+,IP \ restore IP saved by COLON
35319 \ CODE LCD_RDC \ -- char Read Char
35320 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35325 \ ******************************\
35326 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35327 \ ******************************\
35328 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
35329 BIT.B #SW2,&SW2_IN \ test switch S2
35330 0= IF \ case of switch S2 pressed
35331 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
35333 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
35336 BIT.B #SW1,&SW1_IN \ test switch S1 input
35337 0= IF \ case of Switch S1 pressed
35338 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
35340 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
35347 \ ******************************\
35348 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
35349 \ ******************************\
35350 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35351 \ ******************************\
35352 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35353 \ \ SMclock = 8|16|24 MHz
35354 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
35355 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
35356 \ \ SR(9)=new Toggle bit memory (ADD on)
35357 \ ******************************\
35358 \ RC5_FirstStartBitHalfCycle: \
35359 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
35360 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
35361 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
35363 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
35364 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
35366 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
35367 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
35369 MOV #1778,X \ RC5_Period * 1us
35370 MOV #14,W \ count of loop
35372 \ ******************************\
35373 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
35374 \ ******************************\ |
35375 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
35376 \ RC5_Compute_3/4_Period: \ |
35377 RRUM #1,X \ X=1/2 cycle |
35380 ADD X,Y \ Y=3/4 cycle
35381 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
35383 \ ******************************\
35384 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
35385 \ ******************************\
35386 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35387 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
35388 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35389 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35390 SUB #1,W \ decrement count loop
35391 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
35392 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35393 0<> WHILE \ ----> out of loop ----+
35394 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
35396 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
35397 CMP Y,X \ 1 | cycle time out of bound ?
35398 U>= IF \ 2 ^ | yes:
35399 BIC #$30,&RC5_TIM_CTL \ | | stop timer
35400 GOTO FW1 \ | | quit on truncated RC5 message
35402 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
35404 REPEAT \ ----> loop back --+ | with X = new RC5_period value
35405 \ ******************************\ |
35406 \ RC5_SampleEndOf: \ <---------------------+
35407 \ ******************************\
35408 BIC #$30,&RC5_TIM_CTL \ stop timer
35409 \ ******************************\
35410 \ RC5_ComputeNewRC5word \
35411 \ ******************************\
35412 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
35413 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
35414 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
35415 \ ******************************\
35416 \ RC5_ComputeC6bit \
35417 \ ******************************\
35418 BIT #BIT14,T \ test /C6 bit in T
35419 0= IF BIS #BIT6,X \ set C6 bit in X
35420 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
35421 \ ******************************\
35422 \ RC5_CommandByteIsDone \ -- BASE RC5_code
35423 \ ******************************\
35424 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
35425 \ ******************************\
35426 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
35427 XOR @RSP,T \ (new XOR old) Toggle bits
35428 BIT #UF10,T \ repeated RC5_command ?
35429 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
35430 XOR #UF10,0(RSP) \ 5 toggle bit memory
35431 \ ******************************\
35432 \ Display IR_RC5 code \
35433 \ ******************************\
35434 SUB #8,PSP \ TOS -- x x x x TOS
35435 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
35436 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
35437 MOV #$10,&BASEADR \ set hexadecimal base
35438 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
35439 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
35440 LO2HI \ switch from assembler to FORTH
35441 LCD_CLEAR \ set LCD cursor at home
35442 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
35443 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
35444 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
35445 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
35446 HI2LO \ -- switch from FORTH to assembler
35447 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
35448 MOV @PSP+,TOS \ -- TOS
35450 MOV @RSP+,SR \ restore SR flags
35451 BIC #%1111_1000,SR \ but force CPU Active Mode
35452 RET \ (instead of RETI)
35456 \ ------------------------------\
35457 HDNCODE STOP_R2L \ define new STOP_APP
35458 \ ------------------------------\
35459 CMP #RET_ADR,&{RC5TOLCD}+8 \
35460 0<> IF \ if previous START executing
35461 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
35462 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
35463 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
35464 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
35465 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
35466 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
35467 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
35468 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
35469 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
35470 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
35475 \ ------------------------------\
35477 \ ------------------------------\
35478 BW1 \ <-- INI_R2L for some events
35480 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
35482 ." RC5toLCD is removed,"
35483 ." type START to restart"
35486 \ ------------------------------\
35488 \ ------------------------------\
35489 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
35490 \ ------------------------------\
35492 \ ------------------------------\
35493 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
35494 \ ------------------------------\
35495 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
35496 \ ------------------------------\
35497 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
35498 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
35500 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
35501 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
35503 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
35504 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
35505 \ CMP #4,TOS \ hardware RST
35506 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
35507 \ CMP #2,TOS \ Power_ON event
35508 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
35510 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
35512 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
35514 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
35515 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
35516 \ ------------------------------\
35517 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
35518 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35519 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35520 \ -- \ID input divider \ 10 = /4
35521 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
35522 \ - \TBCLR TimerB Clear
35525 \ -------------------------------\
35526 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35527 \ -- \CM Capture Mode
35532 \ --- \OUTMOD \ 011 = set/reset
35538 \ -------------------------------\
35540 \ -------------------------------\
35542 \ ------------------------------\
35543 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
35544 \ ------------------------------\
35545 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
35546 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
35547 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
35548 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
35550 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
35551 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
35553 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
35554 \ ------------------------------\
35555 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
35556 \ ------------------------------\
35557 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
35558 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
35559 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35560 \ ------------------------------\
35561 BIS.B #LCDVo,&LCDVo_DIR \
35562 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
35563 \ ------------------------------\
35564 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35565 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35566 \ ------------------------------\
35567 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35568 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35569 \ ******************************\
35571 \ ******************************\
35572 BIS.B #RC5,&IR_IE \ enable RC5_Int
35573 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35574 \ ******************************\
35575 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
35576 \ ******************************\
35577 \ %01 0001 0100 \ TAxCTL
35578 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
35579 \ -- \ ID divided by 1
35580 \ -- \ MC MODE = up to TAxCCRn
35581 \ - \ TACLR clear timer count
35584 \ ------------------------------\
35585 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
35586 \ ------------------------------\
35588 \ --- \ TAIDEX pre divisor
35589 \ ------------------------------\
35590 \ %0000 0000 0000 0101 \ TAxCCR0
35591 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
35592 \ ------------------------------\
35593 \ %0000 0000 0001 0000 \ TAxCCTL0
35594 \ - \ CAP capture/compare mode = compare
35597 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
35598 \ ------------------------------\
35599 \ define LPM mode for ACCEPT \
35600 \ ------------------------------\
35601 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
35602 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35603 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35604 \ ------------------------------\
35606 \ ------------------------------\
35608 \ ------------------------------\
35609 #1000 20_US \ 1- wait 20 ms
35610 %011 TOP_LCD \ 2- send DB5=DB4=1
35611 #205 20_US \ 3- wait 4,1 ms
35612 %011 TOP_LCD \ 4- send again DB5=DB4=1
35613 #5 20_US \ 5- wait 0,1 ms
35614 %011 TOP_LCD \ 6- send again again DB5=DB4=1
35615 #2 20_US \ wait 40 us = LCD cycle
35616 %010 TOP_LCD \ 7- send DB5=1 DB4=0
35617 #2 20_US \ wait 40 us = LCD cycle
35618 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35619 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35620 LCD_CLEAR \ 10- "LCD_Clear"
35621 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35622 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35623 LCD_CLEAR \ 10- "LCD_Clear"
35624 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35625 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35626 CR ." I love you" \ display message on LCD
35627 ['] CR >BODY IS CR \ CR executes its default value
35628 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
35629 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
35632 \ ------------------------------\
35634 \ ------------------------------\
35635 CODE START \ this routine replaces WARM and COLD default values by these of this application.
35636 \ ------------------------------\
35637 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
35638 0= IF \ if not done, customizes MARKER_DOES
35639 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
35640 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
35641 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
35642 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
35643 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
35644 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
35645 MOV #RC5_INT,&IR_VEC \ init interrupt vector
35646 MOV #INI_R2L,PC \ then execute new INI_APP, without return
35650 \ ------------------------------\
35653 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
35655 MARKER {RC5TOLCD} \ restore the state before MARKER definition
35656 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
35657 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
35658 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
35659 \ {RC5TOLCD}+14: make room to save previous IR_VEC
35661 [UNDEFINED] CONSTANT [IF]
35662 \ https://forth-standard.org/standard/core/CONSTANT
35663 \ CONSTANT <name> n -- define a Forth CONSTANT
35667 MOV TOS,-2(W) \ PFA = n
35674 [UNDEFINED] STATE [IF]
35675 \ https://forth-standard.org/standard/core/STATE
35676 \ STATE -- a-addr holds compiler state
35677 STATEADR CONSTANT STATE
35681 \ https://forth-standard.org/standard/core/Equal
35682 \ = x1 x2 -- flag test x1=x2
35689 XOR #-1,TOS \ 1 flag Z = 1
35694 [UNDEFINED] IF [IF] \ define IF and THEN
35695 \ https://forth-standard.org/standard/core/IF
35696 \ IF -- IFadr initialize conditional forward branch
35697 CODE IF \ immediate
35700 MOV &DP,TOS \ -- HERE
35701 ADD #4,&DP \ compile one word, reserve one word
35702 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
35703 ADD #2,TOS \ -- HERE+2=IFadr
35707 \ https://forth-standard.org/standard/core/THEN
35708 \ THEN IFadr -- resolve forward branch
35709 CODE THEN \ immediate
35710 MOV &DP,0(TOS) \ -- IFadr
35716 [UNDEFINED] ELSE [IF]
35717 \ https://forth-standard.org/standard/core/ELSE
35718 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
35719 CODE ELSE \ immediate
35720 ADD #4,&DP \ make room to compile two words
35721 MOV &DP,W \ W=HERE+4
35723 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
35725 MOV W,TOS \ -- ELSEadr
35730 [UNDEFINED] IS [IF] \ define DEFER! and IS
35732 \ https://forth-standard.org/standard/core/DEFERStore
35733 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
35734 CODE DEFER! \ xt2 xt1 --
35735 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
35740 \ https://forth-standard.org/standard/core/IS
35743 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
35744 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
35745 \ or in a definition : ... ['] U. IS DISPLAY ...
35746 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
35748 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
35752 IF POSTPONE ['] POSTPONE DEFER!
35758 [UNDEFINED] >BODY [IF]
35759 \ https://forth-standard.org/standard/core/toBODY
35760 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
35767 \ CODE 20uS \ n -- 8MHz version
35768 \ BEGIN \ 4 + 16 ~ loop
35769 \ MOV #39,rDOCON \ 39
35776 \ MOV #XDOCON,rDOCON \ 2
35781 CODE 20_US \ n -- n * 20 us
35782 BEGIN \ here we presume that LCD_TIM_IFG = 1...
35784 BIT #1,&LCD_TIM_CTL \ 3
35785 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
35786 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
35788 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
35793 CODE TOP_LCD \ LCD Sample
35794 \ \ if write : %xxxx_WWWW --
35795 \ \ if read : -- %0000_RRRR
35796 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35797 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35798 0= IF \ write LCD bits pattern
35799 AND.B #LCD_DB,TOS \
35800 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35801 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35804 THEN \ read LCD bits pattern
35807 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35808 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35809 AND.B #LCD_DB,TOS \
35813 CODE LCD_WRC \ char -- Write Char
35814 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35816 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
35817 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
35818 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35819 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35820 COLON \ high level word starts here
35821 TOP_LCD 2 20_US \ write high nibble first
35825 CODE LCD_WRF \ func -- Write Fonction
35826 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35830 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
35831 : LCD_HOME $02 LCD_WRF 100 20_us ;
35833 \ [UNDEFINED] OR [IF]
35835 \ \ https://forth-standard.org/standard/core/OR
35836 \ \ C OR x1 x2 -- x3 logical OR
35844 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
35845 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
35846 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
35847 \ : LCD_FN_SET $20 OR LCD_WrF ;
35848 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
35849 \ : LCD_GOTO $80 OR LCD_WrF ;
35852 \ CODE LCD_RDS \ -- status Read Status
35853 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35854 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35855 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35856 \ COLON \ starts a FORTH word
35857 \ TOP_LCD 2 20_us \ -- %0000_HHHH
35858 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
35859 \ HI2LO \ switch from FORTH to assembler
35860 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
35861 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
35862 \ MOV @RSP+,IP \ restore IP saved by COLON
35866 \ CODE LCD_RDC \ -- char Read Char
35867 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35872 \ ******************************\
35873 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35874 \ ******************************\
35875 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
35876 BIT.B #SW2,&SW2_IN \ test switch S2
35877 0= IF \ case of switch S2 pressed
35878 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
35880 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
35883 BIT.B #SW1,&SW1_IN \ test switch S1 input
35884 0= IF \ case of Switch S1 pressed
35885 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
35887 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
35894 \ ******************************\
35895 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
35896 \ ******************************\
35897 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35898 \ ******************************\
35899 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35900 \ \ SMclock = 8|16|24 MHz
35901 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
35902 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
35903 \ \ SR(9)=new Toggle bit memory (ADD on)
35904 \ ******************************\
35905 \ RC5_FirstStartBitHalfCycle: \
35906 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
35907 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
35908 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
35910 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
35911 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
35913 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
35914 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
35916 MOV #1778,X \ RC5_Period * 1us
35917 MOV #14,W \ count of loop
35919 \ ******************************\
35920 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
35921 \ ******************************\ |
35922 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
35923 \ RC5_Compute_3/4_Period: \ |
35924 RRUM #1,X \ X=1/2 cycle |
35927 ADD X,Y \ Y=3/4 cycle
35928 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
35930 \ ******************************\
35931 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
35932 \ ******************************\
35933 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35934 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
35935 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35936 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35937 SUB #1,W \ decrement count loop
35938 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
35939 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35940 0<> WHILE \ ----> out of loop ----+
35941 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
35943 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
35944 CMP Y,X \ 1 | cycle time out of bound ?
35945 U>= IF \ 2 ^ | yes:
35946 BIC #$30,&RC5_TIM_CTL \ | | stop timer
35947 GOTO FW1 \ | | quit on truncated RC5 message
35949 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
35951 REPEAT \ ----> loop back --+ | with X = new RC5_period value
35952 \ ******************************\ |
35953 \ RC5_SampleEndOf: \ <---------------------+
35954 \ ******************************\
35955 BIC #$30,&RC5_TIM_CTL \ stop timer
35956 \ ******************************\
35957 \ RC5_ComputeNewRC5word \
35958 \ ******************************\
35959 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
35960 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
35961 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
35962 \ ******************************\
35963 \ RC5_ComputeC6bit \
35964 \ ******************************\
35965 BIT #BIT14,T \ test /C6 bit in T
35966 0= IF BIS #BIT6,X \ set C6 bit in X
35967 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
35968 \ ******************************\
35969 \ RC5_CommandByteIsDone \ -- BASE RC5_code
35970 \ ******************************\
35971 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
35972 \ ******************************\
35973 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
35974 XOR @RSP,T \ (new XOR old) Toggle bits
35975 BIT #UF10,T \ repeated RC5_command ?
35976 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
35977 XOR #UF10,0(RSP) \ 5 toggle bit memory
35978 \ ******************************\
35979 \ Display IR_RC5 code \
35980 \ ******************************\
35981 SUB #8,PSP \ TOS -- x x x x TOS
35982 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
35983 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
35984 MOV #$10,&BASEADR \ set hexadecimal base
35985 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
35986 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
35987 LO2HI \ switch from assembler to FORTH
35988 LCD_CLEAR \ set LCD cursor at home
35989 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
35990 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
35991 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
35992 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
35993 HI2LO \ -- switch from FORTH to assembler
35994 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
35995 MOV @PSP+,TOS \ -- TOS
35997 MOV @RSP+,SR \ restore SR flags
35998 BIC #%1111_1000,SR \ but force CPU Active Mode
35999 RET \ (instead of RETI)
36003 \ ------------------------------\
36004 HDNCODE STOP_R2L \ define new STOP_APP
36005 \ ------------------------------\
36006 CMP #RET_ADR,&{RC5TOLCD}+8 \
36007 0<> IF \ if previous START executing
36008 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
36009 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
36010 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
36011 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
36012 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
36013 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
36014 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
36015 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
36016 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
36017 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
36022 \ ------------------------------\
36024 \ ------------------------------\
36025 BW1 \ <-- INI_R2L for some events
36027 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
36029 ." RC5toLCD is removed,"
36030 ." type START to restart"
36033 \ ------------------------------\
36035 \ ------------------------------\
36036 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
36037 \ ------------------------------\
36039 \ ------------------------------\
36040 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
36041 \ ------------------------------\
36042 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
36043 \ ------------------------------\
36044 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
36045 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
36047 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
36048 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
36050 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
36051 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
36052 \ CMP #4,TOS \ hardware RST
36053 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
36054 \ CMP #2,TOS \ Power_ON event
36055 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
36057 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
36059 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
36061 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
36062 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
36063 \ ------------------------------\
36064 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
36065 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36066 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36067 \ -- \ID input divider \ 10 = /4
36068 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
36069 \ - \TBCLR TimerB Clear
36072 \ -------------------------------\
36073 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36074 \ -- \CM Capture Mode
36079 \ --- \OUTMOD \ 011 = set/reset
36085 \ -------------------------------\
36087 \ -------------------------------\
36089 \ ------------------------------\
36090 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
36091 \ ------------------------------\
36092 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
36093 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
36094 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
36095 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
36097 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
36098 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
36100 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
36101 \ ------------------------------\
36102 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
36103 \ ------------------------------\
36104 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
36105 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
36106 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36107 \ ------------------------------\
36108 BIS.B #LCDVo,&LCDVo_DIR \
36109 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
36110 \ ------------------------------\
36111 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36112 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36113 \ ------------------------------\
36114 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36115 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36116 \ ******************************\
36118 \ ******************************\
36119 BIS.B #RC5,&IR_IE \ enable RC5_Int
36120 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36121 \ ******************************\
36122 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
36123 \ ******************************\
36124 \ %01 0001 0100 \ TAxCTL
36125 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
36126 \ -- \ ID divided by 1
36127 \ -- \ MC MODE = up to TAxCCRn
36128 \ - \ TACLR clear timer count
36131 \ ------------------------------\
36132 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
36133 \ ------------------------------\
36135 \ --- \ TAIDEX pre divisor
36136 \ ------------------------------\
36137 \ %0000 0000 0000 0101 \ TAxCCR0
36138 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
36139 \ ------------------------------\
36140 \ %0000 0000 0001 0000 \ TAxCCTL0
36141 \ - \ CAP capture/compare mode = compare
36144 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
36145 \ ------------------------------\
36146 \ define LPM mode for ACCEPT \
36147 \ ------------------------------\
36148 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
36149 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36150 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36151 \ ------------------------------\
36153 \ ------------------------------\
36155 \ ------------------------------\
36156 #1000 20_US \ 1- wait 20 ms
36157 %011 TOP_LCD \ 2- send DB5=DB4=1
36158 #205 20_US \ 3- wait 4,1 ms
36159 %011 TOP_LCD \ 4- send again DB5=DB4=1
36160 #5 20_US \ 5- wait 0,1 ms
36161 %011 TOP_LCD \ 6- send again again DB5=DB4=1
36162 #2 20_US \ wait 40 us = LCD cycle
36163 %010 TOP_LCD \ 7- send DB5=1 DB4=0
36164 #2 20_US \ wait 40 us = LCD cycle
36165 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36166 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36167 LCD_CLEAR \ 10- "LCD_Clear"
36168 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36169 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36170 LCD_CLEAR \ 10- "LCD_Clear"
36171 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36172 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36173 CR ." I love you" \ display message on LCD
36174 ['] CR >BODY IS CR \ CR executes its default value
36175 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
36176 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
36179 \ ------------------------------\
36181 \ ------------------------------\
36182 CODE START \ this routine replaces WARM and COLD default values by these of this application.
36183 \ ------------------------------\
36184 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
36185 0= IF \ if not done, customizes MARKER_DOES
36186 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
36187 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
36188 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
36189 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
36190 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
36191 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
36192 MOV #RC5_INT,&IR_VEC \ init interrupt vector
36193 MOV #INI_R2L,PC \ then execute new INI_APP, without return
36197 \ ------------------------------\
36200 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
36202 MARKER {RC5TOLCD} \ restore the state before MARKER definition
36203 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
36204 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
36205 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
36206 \ {RC5TOLCD}+14: make room to save previous IR_VEC
36208 [UNDEFINED] CONSTANT [IF]
36209 \ https://forth-standard.org/standard/core/CONSTANT
36210 \ CONSTANT <name> n -- define a Forth CONSTANT
36214 MOV TOS,-2(W) \ PFA = n
36221 [UNDEFINED] STATE [IF]
36222 \ https://forth-standard.org/standard/core/STATE
36223 \ STATE -- a-addr holds compiler state
36224 STATEADR CONSTANT STATE
36228 \ https://forth-standard.org/standard/core/Equal
36229 \ = x1 x2 -- flag test x1=x2
36236 XOR #-1,TOS \ 1 flag Z = 1
36241 [UNDEFINED] IF [IF] \ define IF and THEN
36242 \ https://forth-standard.org/standard/core/IF
36243 \ IF -- IFadr initialize conditional forward branch
36244 CODE IF \ immediate
36247 MOV &DP,TOS \ -- HERE
36248 ADD #4,&DP \ compile one word, reserve one word
36249 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
36250 ADD #2,TOS \ -- HERE+2=IFadr
36254 \ https://forth-standard.org/standard/core/THEN
36255 \ THEN IFadr -- resolve forward branch
36256 CODE THEN \ immediate
36257 MOV &DP,0(TOS) \ -- IFadr
36263 [UNDEFINED] ELSE [IF]
36264 \ https://forth-standard.org/standard/core/ELSE
36265 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
36266 CODE ELSE \ immediate
36267 ADD #4,&DP \ make room to compile two words
36268 MOV &DP,W \ W=HERE+4
36270 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
36272 MOV W,TOS \ -- ELSEadr
36277 [UNDEFINED] IS [IF] \ define DEFER! and IS
36279 \ https://forth-standard.org/standard/core/DEFERStore
36280 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
36281 CODE DEFER! \ xt2 xt1 --
36282 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
36287 \ https://forth-standard.org/standard/core/IS
36290 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
36291 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
36292 \ or in a definition : ... ['] U. IS DISPLAY ...
36293 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
36295 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
36299 IF POSTPONE ['] POSTPONE DEFER!
36305 [UNDEFINED] >BODY [IF]
36306 \ https://forth-standard.org/standard/core/toBODY
36307 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
36314 \ CODE 20uS \ n -- 8MHz version
36315 \ BEGIN \ 4 + 16 ~ loop
36316 \ MOV #39,rDOCON \ 39
36323 \ MOV #XDOCON,rDOCON \ 2
36328 CODE 20_US \ n -- n * 20 us
36329 BEGIN \ here we presume that LCD_TIM_IFG = 1...
36331 BIT #1,&LCD_TIM_CTL \ 3
36332 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
36333 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
36335 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
36340 CODE TOP_LCD \ LCD Sample
36341 \ \ if write : %xxxx_WWWW --
36342 \ \ if read : -- %0000_RRRR
36343 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36344 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36345 0= IF \ write LCD bits pattern
36346 AND.B #LCD_DB,TOS \
36347 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36348 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36351 THEN \ read LCD bits pattern
36354 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36355 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36356 AND.B #LCD_DB,TOS \
36360 CODE LCD_WRC \ char -- Write Char
36361 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36363 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
36364 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
36365 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36366 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36367 COLON \ high level word starts here
36368 TOP_LCD 2 20_US \ write high nibble first
36372 CODE LCD_WRF \ func -- Write Fonction
36373 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36377 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
36378 : LCD_HOME $02 LCD_WRF 100 20_us ;
36380 \ [UNDEFINED] OR [IF]
36382 \ \ https://forth-standard.org/standard/core/OR
36383 \ \ C OR x1 x2 -- x3 logical OR
36391 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
36392 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
36393 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
36394 \ : LCD_FN_SET $20 OR LCD_WrF ;
36395 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
36396 \ : LCD_GOTO $80 OR LCD_WrF ;
36399 \ CODE LCD_RDS \ -- status Read Status
36400 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36401 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36402 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36403 \ COLON \ starts a FORTH word
36404 \ TOP_LCD 2 20_us \ -- %0000_HHHH
36405 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
36406 \ HI2LO \ switch from FORTH to assembler
36407 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
36408 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
36409 \ MOV @RSP+,IP \ restore IP saved by COLON
36413 \ CODE LCD_RDC \ -- char Read Char
36414 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36419 \ ******************************\
36420 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36421 \ ******************************\
36422 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
36423 BIT.B #SW2,&SW2_IN \ test switch S2
36424 0= IF \ case of switch S2 pressed
36425 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
36427 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
36430 BIT.B #SW1,&SW1_IN \ test switch S1 input
36431 0= IF \ case of Switch S1 pressed
36432 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
36434 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
36441 \ ******************************\
36442 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
36443 \ ******************************\
36444 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36445 \ ******************************\
36446 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36447 \ \ SMclock = 8|16|24 MHz
36448 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
36449 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
36450 \ \ SR(9)=new Toggle bit memory (ADD on)
36451 \ ******************************\
36452 \ RC5_FirstStartBitHalfCycle: \
36453 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
36454 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
36455 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
36457 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
36458 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
36460 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
36461 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
36463 MOV #1778,X \ RC5_Period * 1us
36464 MOV #14,W \ count of loop
36466 \ ******************************\
36467 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
36468 \ ******************************\ |
36469 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
36470 \ RC5_Compute_3/4_Period: \ |
36471 RRUM #1,X \ X=1/2 cycle |
36474 ADD X,Y \ Y=3/4 cycle
36475 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
36477 \ ******************************\
36478 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
36479 \ ******************************\
36480 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36481 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
36482 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36483 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36484 SUB #1,W \ decrement count loop
36485 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
36486 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36487 0<> WHILE \ ----> out of loop ----+
36488 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
36490 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
36491 CMP Y,X \ 1 | cycle time out of bound ?
36492 U>= IF \ 2 ^ | yes:
36493 BIC #$30,&RC5_TIM_CTL \ | | stop timer
36494 GOTO FW1 \ | | quit on truncated RC5 message
36496 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
36498 REPEAT \ ----> loop back --+ | with X = new RC5_period value
36499 \ ******************************\ |
36500 \ RC5_SampleEndOf: \ <---------------------+
36501 \ ******************************\
36502 BIC #$30,&RC5_TIM_CTL \ stop timer
36503 \ ******************************\
36504 \ RC5_ComputeNewRC5word \
36505 \ ******************************\
36506 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
36507 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
36508 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
36509 \ ******************************\
36510 \ RC5_ComputeC6bit \
36511 \ ******************************\
36512 BIT #BIT14,T \ test /C6 bit in T
36513 0= IF BIS #BIT6,X \ set C6 bit in X
36514 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
36515 \ ******************************\
36516 \ RC5_CommandByteIsDone \ -- BASE RC5_code
36517 \ ******************************\
36518 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
36519 \ ******************************\
36520 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
36521 XOR @RSP,T \ (new XOR old) Toggle bits
36522 BIT #UF10,T \ repeated RC5_command ?
36523 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
36524 XOR #UF10,0(RSP) \ 5 toggle bit memory
36525 \ ******************************\
36526 \ Display IR_RC5 code \
36527 \ ******************************\
36528 SUB #8,PSP \ TOS -- x x x x TOS
36529 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
36530 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
36531 MOV #$10,&BASEADR \ set hexadecimal base
36532 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
36533 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
36534 LO2HI \ switch from assembler to FORTH
36535 LCD_CLEAR \ set LCD cursor at home
36536 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
36537 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
36538 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
36539 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
36540 HI2LO \ -- switch from FORTH to assembler
36541 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
36542 MOV @PSP+,TOS \ -- TOS
36544 MOV @RSP+,SR \ restore SR flags
36545 BIC #%1111_1000,SR \ but force CPU Active Mode
36546 RET \ (instead of RETI)
36550 \ ------------------------------\
36551 HDNCODE STOP_R2L \ define new STOP_APP
36552 \ ------------------------------\
36553 CMP #RET_ADR,&{RC5TOLCD}+8 \
36554 0<> IF \ if previous START executing
36555 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
36556 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
36557 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
36558 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
36559 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
36560 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
36561 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
36562 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
36563 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
36564 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
36569 \ ------------------------------\
36571 \ ------------------------------\
36572 BW1 \ <-- INI_R2L for some events
36574 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
36576 ." RC5toLCD is removed,"
36577 ." type START to restart"
36580 \ ------------------------------\
36582 \ ------------------------------\
36583 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
36584 \ ------------------------------\
36586 \ ------------------------------\
36587 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
36588 \ ------------------------------\
36589 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
36590 \ ------------------------------\
36591 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
36592 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
36594 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
36595 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
36597 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
36598 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
36599 \ CMP #4,TOS \ hardware RST
36600 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
36601 \ CMP #2,TOS \ Power_ON event
36602 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
36604 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
36606 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
36608 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
36609 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
36610 \ ------------------------------\
36611 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
36612 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36613 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36614 \ -- \ID input divider \ 10 = /4
36615 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
36616 \ - \TBCLR TimerB Clear
36619 \ -------------------------------\
36620 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36621 \ -- \CM Capture Mode
36626 \ --- \OUTMOD \ 011 = set/reset
36632 \ -------------------------------\
36634 \ -------------------------------\
36636 \ ------------------------------\
36637 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
36638 \ ------------------------------\
36639 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
36640 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
36641 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
36642 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
36644 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
36645 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
36647 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
36648 \ ------------------------------\
36649 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
36650 \ ------------------------------\
36651 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
36652 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
36653 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36654 \ ------------------------------\
36655 BIS.B #LCDVo,&LCDVo_DIR \
36656 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
36657 \ ------------------------------\
36658 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36659 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36660 \ ------------------------------\
36661 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36662 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36663 \ ******************************\
36665 \ ******************************\
36666 BIS.B #RC5,&IR_IE \ enable RC5_Int
36667 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36668 \ ******************************\
36669 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
36670 \ ******************************\
36671 \ %01 0001 0100 \ TAxCTL
36672 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
36673 \ -- \ ID divided by 1
36674 \ -- \ MC MODE = up to TAxCCRn
36675 \ - \ TACLR clear timer count
36678 \ ------------------------------\
36679 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
36680 \ ------------------------------\
36682 \ --- \ TAIDEX pre divisor
36683 \ ------------------------------\
36684 \ %0000 0000 0000 0101 \ TAxCCR0
36685 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
36686 \ ------------------------------\
36687 \ %0000 0000 0001 0000 \ TAxCCTL0
36688 \ - \ CAP capture/compare mode = compare
36691 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
36692 \ ------------------------------\
36693 \ define LPM mode for ACCEPT \
36694 \ ------------------------------\
36695 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
36696 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36697 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36698 \ ------------------------------\
36700 \ ------------------------------\
36702 \ ------------------------------\
36703 #1000 20_US \ 1- wait 20 ms
36704 %011 TOP_LCD \ 2- send DB5=DB4=1
36705 #205 20_US \ 3- wait 4,1 ms
36706 %011 TOP_LCD \ 4- send again DB5=DB4=1
36707 #5 20_US \ 5- wait 0,1 ms
36708 %011 TOP_LCD \ 6- send again again DB5=DB4=1
36709 #2 20_US \ wait 40 us = LCD cycle
36710 %010 TOP_LCD \ 7- send DB5=1 DB4=0
36711 #2 20_US \ wait 40 us = LCD cycle
36712 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36713 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36714 LCD_CLEAR \ 10- "LCD_Clear"
36715 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36716 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36717 LCD_CLEAR \ 10- "LCD_Clear"
36718 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36719 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36720 CR ." I love you" \ display message on LCD
36721 ['] CR >BODY IS CR \ CR executes its default value
36722 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
36723 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
36726 \ ------------------------------\
36728 \ ------------------------------\
36729 CODE START \ this routine replaces WARM and COLD default values by these of this application.
36730 \ ------------------------------\
36731 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
36732 0= IF \ if not done, customizes MARKER_DOES
36733 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
36734 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
36735 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
36736 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
36737 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
36738 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
36739 MOV #RC5_INT,&IR_VEC \ init interrupt vector
36740 MOV #INI_R2L,PC \ then execute new INI_APP, without return
36744 \ ------------------------------\
36747 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
36749 MARKER {RC5TOLCD} \ restore the state before MARKER definition
36750 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
36751 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
36752 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
36753 \ {RC5TOLCD}+14: make room to save previous IR_VEC
36755 [UNDEFINED] CONSTANT [IF]
36756 \ https://forth-standard.org/standard/core/CONSTANT
36757 \ CONSTANT <name> n -- define a Forth CONSTANT
36761 MOV TOS,-2(W) \ PFA = n
36768 [UNDEFINED] STATE [IF]
36769 \ https://forth-standard.org/standard/core/STATE
36770 \ STATE -- a-addr holds compiler state
36771 STATEADR CONSTANT STATE
36775 \ https://forth-standard.org/standard/core/Equal
36776 \ = x1 x2 -- flag test x1=x2
36783 XOR #-1,TOS \ 1 flag Z = 1
36788 [UNDEFINED] IF [IF] \ define IF and THEN
36789 \ https://forth-standard.org/standard/core/IF
36790 \ IF -- IFadr initialize conditional forward branch
36791 CODE IF \ immediate
36794 MOV &DP,TOS \ -- HERE
36795 ADD #4,&DP \ compile one word, reserve one word
36796 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
36797 ADD #2,TOS \ -- HERE+2=IFadr
36801 \ https://forth-standard.org/standard/core/THEN
36802 \ THEN IFadr -- resolve forward branch
36803 CODE THEN \ immediate
36804 MOV &DP,0(TOS) \ -- IFadr
36810 [UNDEFINED] ELSE [IF]
36811 \ https://forth-standard.org/standard/core/ELSE
36812 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
36813 CODE ELSE \ immediate
36814 ADD #4,&DP \ make room to compile two words
36815 MOV &DP,W \ W=HERE+4
36817 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
36819 MOV W,TOS \ -- ELSEadr
36824 [UNDEFINED] IS [IF] \ define DEFER! and IS
36826 \ https://forth-standard.org/standard/core/DEFERStore
36827 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
36828 CODE DEFER! \ xt2 xt1 --
36829 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
36834 \ https://forth-standard.org/standard/core/IS
36837 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
36838 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
36839 \ or in a definition : ... ['] U. IS DISPLAY ...
36840 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
36842 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
36846 IF POSTPONE ['] POSTPONE DEFER!
36852 [UNDEFINED] >BODY [IF]
36853 \ https://forth-standard.org/standard/core/toBODY
36854 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
36861 \ CODE 20uS \ n -- 8MHz version
36862 \ BEGIN \ 4 + 16 ~ loop
36863 \ MOV #39,rDOCON \ 39
36870 \ MOV #XDOCON,rDOCON \ 2
36875 CODE 20_US \ n -- n * 20 us
36876 BEGIN \ here we presume that LCD_TIM_IFG = 1...
36878 BIT #1,&LCD_TIM_CTL \ 3
36879 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
36880 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
36882 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
36887 CODE TOP_LCD \ LCD Sample
36888 \ \ if write : %xxxx_WWWW --
36889 \ \ if read : -- %0000_RRRR
36890 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36891 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36892 0= IF \ write LCD bits pattern
36893 AND.B #LCD_DB,TOS \
36894 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36895 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36898 THEN \ read LCD bits pattern
36901 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36902 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36903 AND.B #LCD_DB,TOS \
36907 CODE LCD_WRC \ char -- Write Char
36908 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36910 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
36911 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
36912 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36913 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36914 COLON \ high level word starts here
36915 TOP_LCD 2 20_US \ write high nibble first
36919 CODE LCD_WRF \ func -- Write Fonction
36920 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36924 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
36925 : LCD_HOME $02 LCD_WRF 100 20_us ;
36927 \ [UNDEFINED] OR [IF]
36929 \ \ https://forth-standard.org/standard/core/OR
36930 \ \ C OR x1 x2 -- x3 logical OR
36938 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
36939 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
36940 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
36941 \ : LCD_FN_SET $20 OR LCD_WrF ;
36942 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
36943 \ : LCD_GOTO $80 OR LCD_WrF ;
36946 \ CODE LCD_RDS \ -- status Read Status
36947 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36948 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36949 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36950 \ COLON \ starts a FORTH word
36951 \ TOP_LCD 2 20_us \ -- %0000_HHHH
36952 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
36953 \ HI2LO \ switch from FORTH to assembler
36954 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
36955 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
36956 \ MOV @RSP+,IP \ restore IP saved by COLON
36960 \ CODE LCD_RDC \ -- char Read Char
36961 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36966 \ ******************************\
36967 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36968 \ ******************************\
36969 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
36970 BIT.B #SW2,&SW2_IN \ test switch S2
36971 0= IF \ case of switch S2 pressed
36972 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
36974 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
36977 BIT.B #SW1,&SW1_IN \ test switch S1 input
36978 0= IF \ case of Switch S1 pressed
36979 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
36981 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
36988 \ ******************************\
36989 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
36990 \ ******************************\
36991 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36992 \ ******************************\
36993 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36994 \ \ SMclock = 8|16|24 MHz
36995 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
36996 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
36997 \ \ SR(9)=new Toggle bit memory (ADD on)
36998 \ ******************************\
36999 \ RC5_FirstStartBitHalfCycle: \
37000 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
37001 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
37002 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
37004 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
37005 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
37007 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
37008 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
37010 MOV #1778,X \ RC5_Period * 1us
37011 MOV #14,W \ count of loop
37013 \ ******************************\
37014 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
37015 \ ******************************\ |
37016 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
37017 \ RC5_Compute_3/4_Period: \ |
37018 RRUM #1,X \ X=1/2 cycle |
37021 ADD X,Y \ Y=3/4 cycle
37022 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
37024 \ ******************************\
37025 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
37026 \ ******************************\
37027 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37028 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
37029 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37030 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37031 SUB #1,W \ decrement count loop
37032 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
37033 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37034 0<> WHILE \ ----> out of loop ----+
37035 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
37037 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
37038 CMP Y,X \ 1 | cycle time out of bound ?
37039 U>= IF \ 2 ^ | yes:
37040 BIC #$30,&RC5_TIM_CTL \ | | stop timer
37041 GOTO FW1 \ | | quit on truncated RC5 message
37043 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
37045 REPEAT \ ----> loop back --+ | with X = new RC5_period value
37046 \ ******************************\ |
37047 \ RC5_SampleEndOf: \ <---------------------+
37048 \ ******************************\
37049 BIC #$30,&RC5_TIM_CTL \ stop timer
37050 \ ******************************\
37051 \ RC5_ComputeNewRC5word \
37052 \ ******************************\
37053 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
37054 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
37055 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
37056 \ ******************************\
37057 \ RC5_ComputeC6bit \
37058 \ ******************************\
37059 BIT #BIT14,T \ test /C6 bit in T
37060 0= IF BIS #BIT6,X \ set C6 bit in X
37061 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
37062 \ ******************************\
37063 \ RC5_CommandByteIsDone \ -- BASE RC5_code
37064 \ ******************************\
37065 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
37066 \ ******************************\
37067 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
37068 XOR @RSP,T \ (new XOR old) Toggle bits
37069 BIT #UF10,T \ repeated RC5_command ?
37070 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
37071 XOR #UF10,0(RSP) \ 5 toggle bit memory
37072 \ ******************************\
37073 \ Display IR_RC5 code \
37074 \ ******************************\
37075 SUB #8,PSP \ TOS -- x x x x TOS
37076 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
37077 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
37078 MOV #$10,&BASEADR \ set hexadecimal base
37079 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
37080 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
37081 LO2HI \ switch from assembler to FORTH
37082 LCD_CLEAR \ set LCD cursor at home
37083 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
37084 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
37085 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
37086 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
37087 HI2LO \ -- switch from FORTH to assembler
37088 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
37089 MOV @PSP+,TOS \ -- TOS
37091 MOV @RSP+,SR \ restore SR flags
37092 BIC #%1111_1000,SR \ but force CPU Active Mode
37093 RET \ (instead of RETI)
37097 \ ------------------------------\
37098 HDNCODE STOP_R2L \ define new STOP_APP
37099 \ ------------------------------\
37100 CMP #RET_ADR,&{RC5TOLCD}+8 \
37101 0<> IF \ if previous START executing
37102 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
37103 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
37104 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
37105 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
37106 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
37107 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
37108 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
37109 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
37110 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
37111 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
37116 \ ------------------------------\
37118 \ ------------------------------\
37119 BW1 \ <-- INI_R2L for some events
37121 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
37123 ." RC5toLCD is removed,"
37124 ." type START to restart"
37127 \ ------------------------------\
37129 \ ------------------------------\
37130 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
37131 \ ------------------------------\
37133 \ ------------------------------\
37134 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
37135 \ ------------------------------\
37136 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
37137 \ ------------------------------\
37138 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
37139 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
37141 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
37142 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
37144 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
37145 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
37146 \ CMP #4,TOS \ hardware RST
37147 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
37148 \ CMP #2,TOS \ Power_ON event
37149 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
37151 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
37153 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
37155 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
37156 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
37157 \ ------------------------------\
37158 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
37159 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37160 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37161 \ -- \ID input divider \ 10 = /4
37162 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
37163 \ - \TBCLR TimerB Clear
37166 \ -------------------------------\
37167 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37168 \ -- \CM Capture Mode
37173 \ --- \OUTMOD \ 011 = set/reset
37179 \ -------------------------------\
37181 \ -------------------------------\
37183 \ ------------------------------\
37184 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
37185 \ ------------------------------\
37186 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
37187 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
37188 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
37189 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
37191 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
37192 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
37194 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
37195 \ ------------------------------\
37196 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
37197 \ ------------------------------\
37198 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
37199 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
37200 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37201 \ ------------------------------\
37202 BIS.B #LCDVo,&LCDVo_DIR \
37203 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
37204 \ ------------------------------\
37205 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37206 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37207 \ ------------------------------\
37208 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37209 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37210 \ ******************************\
37212 \ ******************************\
37213 BIS.B #RC5,&IR_IE \ enable RC5_Int
37214 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37215 \ ******************************\
37216 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
37217 \ ******************************\
37218 \ %01 0001 0100 \ TAxCTL
37219 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
37220 \ -- \ ID divided by 1
37221 \ -- \ MC MODE = up to TAxCCRn
37222 \ - \ TACLR clear timer count
37225 \ ------------------------------\
37226 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
37227 \ ------------------------------\
37229 \ --- \ TAIDEX pre divisor
37230 \ ------------------------------\
37231 \ %0000 0000 0000 0101 \ TAxCCR0
37232 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
37233 \ ------------------------------\
37234 \ %0000 0000 0001 0000 \ TAxCCTL0
37235 \ - \ CAP capture/compare mode = compare
37238 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
37239 \ ------------------------------\
37240 \ define LPM mode for ACCEPT \
37241 \ ------------------------------\
37242 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
37243 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37244 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37245 \ ------------------------------\
37247 \ ------------------------------\
37249 \ ------------------------------\
37250 #1000 20_US \ 1- wait 20 ms
37251 %011 TOP_LCD \ 2- send DB5=DB4=1
37252 #205 20_US \ 3- wait 4,1 ms
37253 %011 TOP_LCD \ 4- send again DB5=DB4=1
37254 #5 20_US \ 5- wait 0,1 ms
37255 %011 TOP_LCD \ 6- send again again DB5=DB4=1
37256 #2 20_US \ wait 40 us = LCD cycle
37257 %010 TOP_LCD \ 7- send DB5=1 DB4=0
37258 #2 20_US \ wait 40 us = LCD cycle
37259 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37260 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37261 LCD_CLEAR \ 10- "LCD_Clear"
37262 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37263 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37264 LCD_CLEAR \ 10- "LCD_Clear"
37265 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37266 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37267 CR ." I love you" \ display message on LCD
37268 ['] CR >BODY IS CR \ CR executes its default value
37269 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
37270 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
37273 \ ------------------------------\
37275 \ ------------------------------\
37276 CODE START \ this routine replaces WARM and COLD default values by these of this application.
37277 \ ------------------------------\
37278 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
37279 0= IF \ if not done, customizes MARKER_DOES
37280 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
37281 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
37282 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
37283 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
37284 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
37285 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
37286 MOV #RC5_INT,&IR_VEC \ init interrupt vector
37287 MOV #INI_R2L,PC \ then execute new INI_APP, without return
37291 \ ------------------------------\
37294 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
37296 MARKER {RC5TOLCD} \ restore the state before MARKER definition
37297 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
37298 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
37299 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
37300 \ {RC5TOLCD}+14: make room to save previous IR_VEC
37302 [UNDEFINED] CONSTANT [IF]
37303 \ https://forth-standard.org/standard/core/CONSTANT
37304 \ CONSTANT <name> n -- define a Forth CONSTANT
37308 MOV TOS,-2(W) \ PFA = n
37315 [UNDEFINED] STATE [IF]
37316 \ https://forth-standard.org/standard/core/STATE
37317 \ STATE -- a-addr holds compiler state
37318 STATEADR CONSTANT STATE
37322 \ https://forth-standard.org/standard/core/Equal
37323 \ = x1 x2 -- flag test x1=x2
37330 XOR #-1,TOS \ 1 flag Z = 1
37335 [UNDEFINED] IF [IF] \ define IF and THEN
37336 \ https://forth-standard.org/standard/core/IF
37337 \ IF -- IFadr initialize conditional forward branch
37338 CODE IF \ immediate
37341 MOV &DP,TOS \ -- HERE
37342 ADD #4,&DP \ compile one word, reserve one word
37343 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
37344 ADD #2,TOS \ -- HERE+2=IFadr
37348 \ https://forth-standard.org/standard/core/THEN
37349 \ THEN IFadr -- resolve forward branch
37350 CODE THEN \ immediate
37351 MOV &DP,0(TOS) \ -- IFadr
37357 [UNDEFINED] ELSE [IF]
37358 \ https://forth-standard.org/standard/core/ELSE
37359 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
37360 CODE ELSE \ immediate
37361 ADD #4,&DP \ make room to compile two words
37362 MOV &DP,W \ W=HERE+4
37364 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
37366 MOV W,TOS \ -- ELSEadr
37371 [UNDEFINED] IS [IF] \ define DEFER! and IS
37373 \ https://forth-standard.org/standard/core/DEFERStore
37374 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
37375 CODE DEFER! \ xt2 xt1 --
37376 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
37381 \ https://forth-standard.org/standard/core/IS
37384 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
37385 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
37386 \ or in a definition : ... ['] U. IS DISPLAY ...
37387 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
37389 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
37393 IF POSTPONE ['] POSTPONE DEFER!
37399 [UNDEFINED] >BODY [IF]
37400 \ https://forth-standard.org/standard/core/toBODY
37401 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
37408 \ CODE 20uS \ n -- 8MHz version
37409 \ BEGIN \ 4 + 16 ~ loop
37410 \ MOV #39,rDOCON \ 39
37417 \ MOV #XDOCON,rDOCON \ 2
37422 CODE 20_US \ n -- n * 20 us
37423 BEGIN \ here we presume that LCD_TIM_IFG = 1...
37425 BIT #1,&LCD_TIM_CTL \ 3
37426 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
37427 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
37429 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
37434 CODE TOP_LCD \ LCD Sample
37435 \ \ if write : %xxxx_WWWW --
37436 \ \ if read : -- %0000_RRRR
37437 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37438 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37439 0= IF \ write LCD bits pattern
37440 AND.B #LCD_DB,TOS \
37441 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37442 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37445 THEN \ read LCD bits pattern
37448 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37449 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37450 AND.B #LCD_DB,TOS \
37454 CODE LCD_WRC \ char -- Write Char
37455 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37457 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
37458 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
37459 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37460 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37461 COLON \ high level word starts here
37462 TOP_LCD 2 20_US \ write high nibble first
37466 CODE LCD_WRF \ func -- Write Fonction
37467 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37471 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
37472 : LCD_HOME $02 LCD_WRF 100 20_us ;
37474 \ [UNDEFINED] OR [IF]
37476 \ \ https://forth-standard.org/standard/core/OR
37477 \ \ C OR x1 x2 -- x3 logical OR
37485 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
37486 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
37487 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
37488 \ : LCD_FN_SET $20 OR LCD_WrF ;
37489 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
37490 \ : LCD_GOTO $80 OR LCD_WrF ;
37493 \ CODE LCD_RDS \ -- status Read Status
37494 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37495 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37496 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37497 \ COLON \ starts a FORTH word
37498 \ TOP_LCD 2 20_us \ -- %0000_HHHH
37499 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
37500 \ HI2LO \ switch from FORTH to assembler
37501 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
37502 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
37503 \ MOV @RSP+,IP \ restore IP saved by COLON
37507 \ CODE LCD_RDC \ -- char Read Char
37508 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37513 \ ******************************\
37514 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
37515 \ ******************************\
37516 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
37517 BIT.B #SW2,&SW2_IN \ test switch S2
37518 0= IF \ case of switch S2 pressed
37519 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
37521 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
37524 BIT.B #SW1,&SW1_IN \ test switch S1 input
37525 0= IF \ case of Switch S1 pressed
37526 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
37528 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
37535 \ ******************************\
37536 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
37537 \ ******************************\
37538 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
37539 \ ******************************\
37540 \ \ in : SR(9)=old Toggle bit memory (ADD on)
37541 \ \ SMclock = 8|16|24 MHz
37542 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
37543 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
37544 \ \ SR(9)=new Toggle bit memory (ADD on)
37545 \ ******************************\
37546 \ RC5_FirstStartBitHalfCycle: \
37547 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
37548 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
37549 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
37551 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
37552 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
37554 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
37555 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
37557 MOV #1778,X \ RC5_Period * 1us
37558 MOV #14,W \ count of loop
37560 \ ******************************\
37561 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
37562 \ ******************************\ |
37563 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
37564 \ RC5_Compute_3/4_Period: \ |
37565 RRUM #1,X \ X=1/2 cycle |
37568 ADD X,Y \ Y=3/4 cycle
37569 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
37571 \ ******************************\
37572 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
37573 \ ******************************\
37574 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37575 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
37576 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37577 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37578 SUB #1,W \ decrement count loop
37579 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
37580 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37581 0<> WHILE \ ----> out of loop ----+
37582 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
37584 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
37585 CMP Y,X \ 1 | cycle time out of bound ?
37586 U>= IF \ 2 ^ | yes:
37587 BIC #$30,&RC5_TIM_CTL \ | | stop timer
37588 GOTO FW1 \ | | quit on truncated RC5 message
37590 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
37592 REPEAT \ ----> loop back --+ | with X = new RC5_period value
37593 \ ******************************\ |
37594 \ RC5_SampleEndOf: \ <---------------------+
37595 \ ******************************\
37596 BIC #$30,&RC5_TIM_CTL \ stop timer
37597 \ ******************************\
37598 \ RC5_ComputeNewRC5word \
37599 \ ******************************\
37600 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
37601 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
37602 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
37603 \ ******************************\
37604 \ RC5_ComputeC6bit \
37605 \ ******************************\
37606 BIT #BIT14,T \ test /C6 bit in T
37607 0= IF BIS #BIT6,X \ set C6 bit in X
37608 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
37609 \ ******************************\
37610 \ RC5_CommandByteIsDone \ -- BASE RC5_code
37611 \ ******************************\
37612 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
37613 \ ******************************\
37614 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
37615 XOR @RSP,T \ (new XOR old) Toggle bits
37616 BIT #UF10,T \ repeated RC5_command ?
37617 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
37618 XOR #UF10,0(RSP) \ 5 toggle bit memory
37619 \ ******************************\
37620 \ Display IR_RC5 code \
37621 \ ******************************\
37622 SUB #8,PSP \ TOS -- x x x x TOS
37623 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
37624 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
37625 MOV #$10,&BASEADR \ set hexadecimal base
37626 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
37627 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
37628 LO2HI \ switch from assembler to FORTH
37629 LCD_CLEAR \ set LCD cursor at home
37630 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
37631 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
37632 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
37633 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
37634 HI2LO \ -- switch from FORTH to assembler
37635 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
37636 MOV @PSP+,TOS \ -- TOS
37638 MOV @RSP+,SR \ restore SR flags
37639 BIC #%1111_1000,SR \ but force CPU Active Mode
37640 RET \ (instead of RETI)
37644 \ ------------------------------\
37645 HDNCODE STOP_R2L \ define new STOP_APP
37646 \ ------------------------------\
37647 CMP #RET_ADR,&{RC5TOLCD}+8 \
37648 0<> IF \ if previous START executing
37649 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
37650 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
37651 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
37652 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
37653 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
37654 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
37655 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
37656 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
37657 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
37658 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
37663 \ ------------------------------\
37665 \ ------------------------------\
37666 BW1 \ <-- INI_R2L for some events
37668 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
37670 ." RC5toLCD is removed,"
37671 ." type START to restart"
37674 \ ------------------------------\
37676 \ ------------------------------\
37677 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
37678 \ ------------------------------\
37680 \ ------------------------------\
37681 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
37682 \ ------------------------------\
37683 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
37684 \ ------------------------------\
37685 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
37686 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
37688 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
37689 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
37691 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
37692 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
37693 \ CMP #4,TOS \ hardware RST
37694 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
37695 \ CMP #2,TOS \ Power_ON event
37696 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
37698 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
37700 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
37702 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
37703 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
37704 \ ------------------------------\
37705 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
37706 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37707 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37708 \ -- \ID input divider \ 10 = /4
37709 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
37710 \ - \TBCLR TimerB Clear
37713 \ -------------------------------\
37714 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37715 \ -- \CM Capture Mode
37720 \ --- \OUTMOD \ 011 = set/reset
37726 \ -------------------------------\
37728 \ -------------------------------\
37730 \ ------------------------------\
37731 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
37732 \ ------------------------------\
37733 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
37734 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
37735 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
37736 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
37738 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
37739 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
37741 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
37742 \ ------------------------------\
37743 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
37744 \ ------------------------------\
37745 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
37746 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
37747 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37748 \ ------------------------------\
37749 BIS.B #LCDVo,&LCDVo_DIR \
37750 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
37751 \ ------------------------------\
37752 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37753 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37754 \ ------------------------------\
37755 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37756 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37757 \ ******************************\
37759 \ ******************************\
37760 BIS.B #RC5,&IR_IE \ enable RC5_Int
37761 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37762 \ ******************************\
37763 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
37764 \ ******************************\
37765 \ %01 0001 0100 \ TAxCTL
37766 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
37767 \ -- \ ID divided by 1
37768 \ -- \ MC MODE = up to TAxCCRn
37769 \ - \ TACLR clear timer count
37772 \ ------------------------------\
37773 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
37774 \ ------------------------------\
37776 \ --- \ TAIDEX pre divisor
37777 \ ------------------------------\
37778 \ %0000 0000 0000 0101 \ TAxCCR0
37779 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
37780 \ ------------------------------\
37781 \ %0000 0000 0001 0000 \ TAxCCTL0
37782 \ - \ CAP capture/compare mode = compare
37785 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
37786 \ ------------------------------\
37787 \ define LPM mode for ACCEPT \
37788 \ ------------------------------\
37789 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
37790 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37791 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37792 \ ------------------------------\
37794 \ ------------------------------\
37796 \ ------------------------------\
37797 #1000 20_US \ 1- wait 20 ms
37798 %011 TOP_LCD \ 2- send DB5=DB4=1
37799 #205 20_US \ 3- wait 4,1 ms
37800 %011 TOP_LCD \ 4- send again DB5=DB4=1
37801 #5 20_US \ 5- wait 0,1 ms
37802 %011 TOP_LCD \ 6- send again again DB5=DB4=1
37803 #2 20_US \ wait 40 us = LCD cycle
37804 %010 TOP_LCD \ 7- send DB5=1 DB4=0
37805 #2 20_US \ wait 40 us = LCD cycle
37806 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37807 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37808 LCD_CLEAR \ 10- "LCD_Clear"
37809 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37810 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37811 LCD_CLEAR \ 10- "LCD_Clear"
37812 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37813 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37814 CR ." I love you" \ display message on LCD
37815 ['] CR >BODY IS CR \ CR executes its default value
37816 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
37817 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
37820 \ ------------------------------\
37822 \ ------------------------------\
37823 CODE START \ this routine replaces WARM and COLD default values by these of this application.
37824 \ ------------------------------\
37825 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
37826 0= IF \ if not done, customizes MARKER_DOES
37827 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
37828 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
37829 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
37830 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
37831 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
37832 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
37833 MOV #RC5_INT,&IR_VEC \ init interrupt vector
37834 MOV #INI_R2L,PC \ then execute new INI_APP, without return
37838 \ ------------------------------\
37841 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
37843 MARKER {RC5TOLCD} \ restore the state before MARKER definition
37844 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
37845 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
37846 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
37847 \ {RC5TOLCD}+14: make room to save previous IR_VEC
37849 [UNDEFINED] CONSTANT [IF]
37850 \ https://forth-standard.org/standard/core/CONSTANT
37851 \ CONSTANT <name> n -- define a Forth CONSTANT
37855 MOV TOS,-2(W) \ PFA = n
37862 [UNDEFINED] STATE [IF]
37863 \ https://forth-standard.org/standard/core/STATE
37864 \ STATE -- a-addr holds compiler state
37865 STATEADR CONSTANT STATE
37869 \ https://forth-standard.org/standard/core/Equal
37870 \ = x1 x2 -- flag test x1=x2
37877 XOR #-1,TOS \ 1 flag Z = 1
37882 [UNDEFINED] IF [IF] \ define IF and THEN
37883 \ https://forth-standard.org/standard/core/IF
37884 \ IF -- IFadr initialize conditional forward branch
37885 CODE IF \ immediate
37888 MOV &DP,TOS \ -- HERE
37889 ADD #4,&DP \ compile one word, reserve one word
37890 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
37891 ADD #2,TOS \ -- HERE+2=IFadr
37895 \ https://forth-standard.org/standard/core/THEN
37896 \ THEN IFadr -- resolve forward branch
37897 CODE THEN \ immediate
37898 MOV &DP,0(TOS) \ -- IFadr
37904 [UNDEFINED] ELSE [IF]
37905 \ https://forth-standard.org/standard/core/ELSE
37906 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
37907 CODE ELSE \ immediate
37908 ADD #4,&DP \ make room to compile two words
37909 MOV &DP,W \ W=HERE+4
37911 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
37913 MOV W,TOS \ -- ELSEadr
37918 [UNDEFINED] IS [IF] \ define DEFER! and IS
37920 \ https://forth-standard.org/standard/core/DEFERStore
37921 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
37922 CODE DEFER! \ xt2 xt1 --
37923 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
37928 \ https://forth-standard.org/standard/core/IS
37931 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
37932 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
37933 \ or in a definition : ... ['] U. IS DISPLAY ...
37934 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
37936 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
37940 IF POSTPONE ['] POSTPONE DEFER!
37946 [UNDEFINED] >BODY [IF]
37947 \ https://forth-standard.org/standard/core/toBODY
37948 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
37955 \ CODE 20uS \ n -- 8MHz version
37956 \ BEGIN \ 4 + 16 ~ loop
37957 \ MOV #39,rDOCON \ 39
37964 \ MOV #XDOCON,rDOCON \ 2
37969 CODE 20_US \ n -- n * 20 us
37970 BEGIN \ here we presume that LCD_TIM_IFG = 1...
37972 BIT #1,&LCD_TIM_CTL \ 3
37973 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
37974 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
37976 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
37981 CODE TOP_LCD \ LCD Sample
37982 \ \ if write : %xxxx_WWWW --
37983 \ \ if read : -- %0000_RRRR
37984 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37985 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37986 0= IF \ write LCD bits pattern
37987 AND.B #LCD_DB,TOS \
37988 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37989 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37992 THEN \ read LCD bits pattern
37995 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37996 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37997 AND.B #LCD_DB,TOS \
38001 CODE LCD_WRC \ char -- Write Char
38002 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38004 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
38005 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
38006 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38007 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38008 COLON \ high level word starts here
38009 TOP_LCD 2 20_US \ write high nibble first
38013 CODE LCD_WRF \ func -- Write Fonction
38014 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38018 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
38019 : LCD_HOME $02 LCD_WRF 100 20_us ;
38021 \ [UNDEFINED] OR [IF]
38023 \ \ https://forth-standard.org/standard/core/OR
38024 \ \ C OR x1 x2 -- x3 logical OR
38032 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
38033 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
38034 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
38035 \ : LCD_FN_SET $20 OR LCD_WrF ;
38036 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
38037 \ : LCD_GOTO $80 OR LCD_WrF ;
38040 \ CODE LCD_RDS \ -- status Read Status
38041 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38042 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38043 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38044 \ COLON \ starts a FORTH word
38045 \ TOP_LCD 2 20_us \ -- %0000_HHHH
38046 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
38047 \ HI2LO \ switch from FORTH to assembler
38048 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
38049 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
38050 \ MOV @RSP+,IP \ restore IP saved by COLON
38054 \ CODE LCD_RDC \ -- char Read Char
38055 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38060 \ ******************************\
38061 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38062 \ ******************************\
38063 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
38064 BIT.B #SW2,&SW2_IN \ test switch S2
38065 0= IF \ case of switch S2 pressed
38066 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
38068 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
38071 BIT.B #SW1,&SW1_IN \ test switch S1 input
38072 0= IF \ case of Switch S1 pressed
38073 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
38075 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
38082 \ ******************************\
38083 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
38084 \ ******************************\
38085 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38086 \ ******************************\
38087 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38088 \ \ SMclock = 8|16|24 MHz
38089 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
38090 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
38091 \ \ SR(9)=new Toggle bit memory (ADD on)
38092 \ ******************************\
38093 \ RC5_FirstStartBitHalfCycle: \
38094 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
38095 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
38096 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
38098 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
38099 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
38101 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
38102 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
38104 MOV #1778,X \ RC5_Period * 1us
38105 MOV #14,W \ count of loop
38107 \ ******************************\
38108 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
38109 \ ******************************\ |
38110 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
38111 \ RC5_Compute_3/4_Period: \ |
38112 RRUM #1,X \ X=1/2 cycle |
38115 ADD X,Y \ Y=3/4 cycle
38116 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
38118 \ ******************************\
38119 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
38120 \ ******************************\
38121 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38122 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
38123 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38124 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38125 SUB #1,W \ decrement count loop
38126 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
38127 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38128 0<> WHILE \ ----> out of loop ----+
38129 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
38131 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
38132 CMP Y,X \ 1 | cycle time out of bound ?
38133 U>= IF \ 2 ^ | yes:
38134 BIC #$30,&RC5_TIM_CTL \ | | stop timer
38135 GOTO FW1 \ | | quit on truncated RC5 message
38137 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
38139 REPEAT \ ----> loop back --+ | with X = new RC5_period value
38140 \ ******************************\ |
38141 \ RC5_SampleEndOf: \ <---------------------+
38142 \ ******************************\
38143 BIC #$30,&RC5_TIM_CTL \ stop timer
38144 \ ******************************\
38145 \ RC5_ComputeNewRC5word \
38146 \ ******************************\
38147 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
38148 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
38149 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
38150 \ ******************************\
38151 \ RC5_ComputeC6bit \
38152 \ ******************************\
38153 BIT #BIT14,T \ test /C6 bit in T
38154 0= IF BIS #BIT6,X \ set C6 bit in X
38155 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
38156 \ ******************************\
38157 \ RC5_CommandByteIsDone \ -- BASE RC5_code
38158 \ ******************************\
38159 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
38160 \ ******************************\
38161 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
38162 XOR @RSP,T \ (new XOR old) Toggle bits
38163 BIT #UF10,T \ repeated RC5_command ?
38164 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
38165 XOR #UF10,0(RSP) \ 5 toggle bit memory
38166 \ ******************************\
38167 \ Display IR_RC5 code \
38168 \ ******************************\
38169 SUB #8,PSP \ TOS -- x x x x TOS
38170 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
38171 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
38172 MOV #$10,&BASEADR \ set hexadecimal base
38173 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
38174 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
38175 LO2HI \ switch from assembler to FORTH
38176 LCD_CLEAR \ set LCD cursor at home
38177 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
38178 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
38179 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
38180 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
38181 HI2LO \ -- switch from FORTH to assembler
38182 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
38183 MOV @PSP+,TOS \ -- TOS
38185 MOV @RSP+,SR \ restore SR flags
38186 BIC #%1111_1000,SR \ but force CPU Active Mode
38187 RET \ (instead of RETI)
38191 \ ------------------------------\
38192 HDNCODE STOP_R2L \ define new STOP_APP
38193 \ ------------------------------\
38194 CMP #RET_ADR,&{RC5TOLCD}+8 \
38195 0<> IF \ if previous START executing
38196 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
38197 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
38198 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
38199 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
38200 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
38201 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
38202 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
38203 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
38204 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
38205 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
38210 \ ------------------------------\
38212 \ ------------------------------\
38213 BW1 \ <-- INI_R2L for some events
38215 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
38217 ." RC5toLCD is removed,"
38218 ." type START to restart"
38221 \ ------------------------------\
38223 \ ------------------------------\
38224 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
38225 \ ------------------------------\
38227 \ ------------------------------\
38228 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
38229 \ ------------------------------\
38230 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
38231 \ ------------------------------\
38232 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
38233 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
38235 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
38236 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
38238 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
38239 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
38240 \ CMP #4,TOS \ hardware RST
38241 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
38242 \ CMP #2,TOS \ Power_ON event
38243 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
38245 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
38247 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
38249 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
38250 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
38251 \ ------------------------------\
38252 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
38253 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38254 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38255 \ -- \ID input divider \ 10 = /4
38256 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
38257 \ - \TBCLR TimerB Clear
38260 \ -------------------------------\
38261 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38262 \ -- \CM Capture Mode
38267 \ --- \OUTMOD \ 011 = set/reset
38273 \ -------------------------------\
38275 \ -------------------------------\
38277 \ ------------------------------\
38278 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
38279 \ ------------------------------\
38280 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
38281 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
38282 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
38283 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
38285 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
38286 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
38288 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
38289 \ ------------------------------\
38290 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
38291 \ ------------------------------\
38292 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
38293 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
38294 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38295 \ ------------------------------\
38296 BIS.B #LCDVo,&LCDVo_DIR \
38297 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
38298 \ ------------------------------\
38299 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38300 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38301 \ ------------------------------\
38302 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38303 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38304 \ ******************************\
38306 \ ******************************\
38307 BIS.B #RC5,&IR_IE \ enable RC5_Int
38308 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38309 \ ******************************\
38310 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
38311 \ ******************************\
38312 \ %01 0001 0100 \ TAxCTL
38313 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
38314 \ -- \ ID divided by 1
38315 \ -- \ MC MODE = up to TAxCCRn
38316 \ - \ TACLR clear timer count
38319 \ ------------------------------\
38320 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
38321 \ ------------------------------\
38323 \ --- \ TAIDEX pre divisor
38324 \ ------------------------------\
38325 \ %0000 0000 0000 0101 \ TAxCCR0
38326 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
38327 \ ------------------------------\
38328 \ %0000 0000 0001 0000 \ TAxCCTL0
38329 \ - \ CAP capture/compare mode = compare
38332 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
38333 \ ------------------------------\
38334 \ define LPM mode for ACCEPT \
38335 \ ------------------------------\
38336 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
38337 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38338 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38339 \ ------------------------------\
38341 \ ------------------------------\
38343 \ ------------------------------\
38344 #1000 20_US \ 1- wait 20 ms
38345 %011 TOP_LCD \ 2- send DB5=DB4=1
38346 #205 20_US \ 3- wait 4,1 ms
38347 %011 TOP_LCD \ 4- send again DB5=DB4=1
38348 #5 20_US \ 5- wait 0,1 ms
38349 %011 TOP_LCD \ 6- send again again DB5=DB4=1
38350 #2 20_US \ wait 40 us = LCD cycle
38351 %010 TOP_LCD \ 7- send DB5=1 DB4=0
38352 #2 20_US \ wait 40 us = LCD cycle
38353 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38354 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38355 LCD_CLEAR \ 10- "LCD_Clear"
38356 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38357 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38358 LCD_CLEAR \ 10- "LCD_Clear"
38359 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38360 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38361 CR ." I love you" \ display message on LCD
38362 ['] CR >BODY IS CR \ CR executes its default value
38363 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
38364 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
38367 \ ------------------------------\
38369 \ ------------------------------\
38370 CODE START \ this routine replaces WARM and COLD default values by these of this application.
38371 \ ------------------------------\
38372 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
38373 0= IF \ if not done, customizes MARKER_DOES
38374 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
38375 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
38376 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
38377 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
38378 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
38379 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
38380 MOV #RC5_INT,&IR_VEC \ init interrupt vector
38381 MOV #INI_R2L,PC \ then execute new INI_APP, without return
38385 \ ------------------------------\
38388 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
38390 MARKER {RC5TOLCD} \ restore the state before MARKER definition
38391 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
38392 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
38393 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
38394 \ {RC5TOLCD}+14: make room to save previous IR_VEC
38396 [UNDEFINED] CONSTANT [IF]
38397 \ https://forth-standard.org/standard/core/CONSTANT
38398 \ CONSTANT <name> n -- define a Forth CONSTANT
38402 MOV TOS,-2(W) \ PFA = n
38409 [UNDEFINED] STATE [IF]
38410 \ https://forth-standard.org/standard/core/STATE
38411 \ STATE -- a-addr holds compiler state
38412 STATEADR CONSTANT STATE
38416 \ https://forth-standard.org/standard/core/Equal
38417 \ = x1 x2 -- flag test x1=x2
38424 XOR #-1,TOS \ 1 flag Z = 1
38429 [UNDEFINED] IF [IF] \ define IF and THEN
38430 \ https://forth-standard.org/standard/core/IF
38431 \ IF -- IFadr initialize conditional forward branch
38432 CODE IF \ immediate
38435 MOV &DP,TOS \ -- HERE
38436 ADD #4,&DP \ compile one word, reserve one word
38437 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
38438 ADD #2,TOS \ -- HERE+2=IFadr
38442 \ https://forth-standard.org/standard/core/THEN
38443 \ THEN IFadr -- resolve forward branch
38444 CODE THEN \ immediate
38445 MOV &DP,0(TOS) \ -- IFadr
38451 [UNDEFINED] ELSE [IF]
38452 \ https://forth-standard.org/standard/core/ELSE
38453 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
38454 CODE ELSE \ immediate
38455 ADD #4,&DP \ make room to compile two words
38456 MOV &DP,W \ W=HERE+4
38458 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
38460 MOV W,TOS \ -- ELSEadr
38465 [UNDEFINED] IS [IF] \ define DEFER! and IS
38467 \ https://forth-standard.org/standard/core/DEFERStore
38468 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
38469 CODE DEFER! \ xt2 xt1 --
38470 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
38475 \ https://forth-standard.org/standard/core/IS
38478 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
38479 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
38480 \ or in a definition : ... ['] U. IS DISPLAY ...
38481 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
38483 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
38487 IF POSTPONE ['] POSTPONE DEFER!
38493 [UNDEFINED] >BODY [IF]
38494 \ https://forth-standard.org/standard/core/toBODY
38495 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
38502 \ CODE 20uS \ n -- 8MHz version
38503 \ BEGIN \ 4 + 16 ~ loop
38504 \ MOV #39,rDOCON \ 39
38511 \ MOV #XDOCON,rDOCON \ 2
38516 CODE 20_US \ n -- n * 20 us
38517 BEGIN \ here we presume that LCD_TIM_IFG = 1...
38519 BIT #1,&LCD_TIM_CTL \ 3
38520 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
38521 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
38523 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
38528 CODE TOP_LCD \ LCD Sample
38529 \ \ if write : %xxxx_WWWW --
38530 \ \ if read : -- %0000_RRRR
38531 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38532 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38533 0= IF \ write LCD bits pattern
38534 AND.B #LCD_DB,TOS \
38535 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38536 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38539 THEN \ read LCD bits pattern
38542 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38543 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38544 AND.B #LCD_DB,TOS \
38548 CODE LCD_WRC \ char -- Write Char
38549 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38551 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
38552 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
38553 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38554 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38555 COLON \ high level word starts here
38556 TOP_LCD 2 20_US \ write high nibble first
38560 CODE LCD_WRF \ func -- Write Fonction
38561 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38565 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
38566 : LCD_HOME $02 LCD_WRF 100 20_us ;
38568 \ [UNDEFINED] OR [IF]
38570 \ \ https://forth-standard.org/standard/core/OR
38571 \ \ C OR x1 x2 -- x3 logical OR
38579 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
38580 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
38581 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
38582 \ : LCD_FN_SET $20 OR LCD_WrF ;
38583 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
38584 \ : LCD_GOTO $80 OR LCD_WrF ;
38587 \ CODE LCD_RDS \ -- status Read Status
38588 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38589 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38590 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38591 \ COLON \ starts a FORTH word
38592 \ TOP_LCD 2 20_us \ -- %0000_HHHH
38593 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
38594 \ HI2LO \ switch from FORTH to assembler
38595 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
38596 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
38597 \ MOV @RSP+,IP \ restore IP saved by COLON
38601 \ CODE LCD_RDC \ -- char Read Char
38602 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38607 \ ******************************\
38608 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38609 \ ******************************\
38610 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
38611 BIT.B #SW2,&SW2_IN \ test switch S2
38612 0= IF \ case of switch S2 pressed
38613 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
38615 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
38618 BIT.B #SW1,&SW1_IN \ test switch S1 input
38619 0= IF \ case of Switch S1 pressed
38620 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
38622 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
38629 \ ******************************\
38630 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
38631 \ ******************************\
38632 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38633 \ ******************************\
38634 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38635 \ \ SMclock = 8|16|24 MHz
38636 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
38637 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
38638 \ \ SR(9)=new Toggle bit memory (ADD on)
38639 \ ******************************\
38640 \ RC5_FirstStartBitHalfCycle: \
38641 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
38642 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
38643 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
38645 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
38646 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
38648 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
38649 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
38651 MOV #1778,X \ RC5_Period * 1us
38652 MOV #14,W \ count of loop
38654 \ ******************************\
38655 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
38656 \ ******************************\ |
38657 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
38658 \ RC5_Compute_3/4_Period: \ |
38659 RRUM #1,X \ X=1/2 cycle |
38662 ADD X,Y \ Y=3/4 cycle
38663 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
38665 \ ******************************\
38666 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
38667 \ ******************************\
38668 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38669 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
38670 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38671 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38672 SUB #1,W \ decrement count loop
38673 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
38674 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38675 0<> WHILE \ ----> out of loop ----+
38676 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
38678 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
38679 CMP Y,X \ 1 | cycle time out of bound ?
38680 U>= IF \ 2 ^ | yes:
38681 BIC #$30,&RC5_TIM_CTL \ | | stop timer
38682 GOTO FW1 \ | | quit on truncated RC5 message
38684 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
38686 REPEAT \ ----> loop back --+ | with X = new RC5_period value
38687 \ ******************************\ |
38688 \ RC5_SampleEndOf: \ <---------------------+
38689 \ ******************************\
38690 BIC #$30,&RC5_TIM_CTL \ stop timer
38691 \ ******************************\
38692 \ RC5_ComputeNewRC5word \
38693 \ ******************************\
38694 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
38695 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
38696 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
38697 \ ******************************\
38698 \ RC5_ComputeC6bit \
38699 \ ******************************\
38700 BIT #BIT14,T \ test /C6 bit in T
38701 0= IF BIS #BIT6,X \ set C6 bit in X
38702 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
38703 \ ******************************\
38704 \ RC5_CommandByteIsDone \ -- BASE RC5_code
38705 \ ******************************\
38706 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
38707 \ ******************************\
38708 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
38709 XOR @RSP,T \ (new XOR old) Toggle bits
38710 BIT #UF10,T \ repeated RC5_command ?
38711 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
38712 XOR #UF10,0(RSP) \ 5 toggle bit memory
38713 \ ******************************\
38714 \ Display IR_RC5 code \
38715 \ ******************************\
38716 SUB #8,PSP \ TOS -- x x x x TOS
38717 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
38718 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
38719 MOV #$10,&BASEADR \ set hexadecimal base
38720 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
38721 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
38722 LO2HI \ switch from assembler to FORTH
38723 LCD_CLEAR \ set LCD cursor at home
38724 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
38725 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
38726 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
38727 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
38728 HI2LO \ -- switch from FORTH to assembler
38729 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
38730 MOV @PSP+,TOS \ -- TOS
38732 MOV @RSP+,SR \ restore SR flags
38733 BIC #%1111_1000,SR \ but force CPU Active Mode
38734 RET \ (instead of RETI)
38738 \ ------------------------------\
38739 HDNCODE STOP_R2L \ define new STOP_APP
38740 \ ------------------------------\
38741 CMP #RET_ADR,&{RC5TOLCD}+8 \
38742 0<> IF \ if previous START executing
38743 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
38744 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
38745 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
38746 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
38747 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
38748 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
38749 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
38750 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
38751 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
38752 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
38757 \ ------------------------------\
38759 \ ------------------------------\
38760 BW1 \ <-- INI_R2L for some events
38762 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
38764 ." RC5toLCD is removed,"
38765 ." type START to restart"
38768 \ ------------------------------\
38770 \ ------------------------------\
38771 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
38772 \ ------------------------------\
38774 \ ------------------------------\
38775 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
38776 \ ------------------------------\
38777 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
38778 \ ------------------------------\
38779 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
38780 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
38782 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
38783 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
38785 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
38786 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
38787 \ CMP #4,TOS \ hardware RST
38788 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
38789 \ CMP #2,TOS \ Power_ON event
38790 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
38792 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
38794 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
38796 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
38797 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
38798 \ ------------------------------\
38799 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
38800 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38801 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38802 \ -- \ID input divider \ 10 = /4
38803 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
38804 \ - \TBCLR TimerB Clear
38807 \ -------------------------------\
38808 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38809 \ -- \CM Capture Mode
38814 \ --- \OUTMOD \ 011 = set/reset
38820 \ -------------------------------\
38822 \ -------------------------------\
38824 \ ------------------------------\
38825 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
38826 \ ------------------------------\
38827 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
38828 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
38829 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
38830 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
38832 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
38833 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
38835 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
38836 \ ------------------------------\
38837 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
38838 \ ------------------------------\
38839 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
38840 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
38841 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38842 \ ------------------------------\
38843 BIS.B #LCDVo,&LCDVo_DIR \
38844 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
38845 \ ------------------------------\
38846 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38847 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38848 \ ------------------------------\
38849 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38850 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38851 \ ******************************\
38853 \ ******************************\
38854 BIS.B #RC5,&IR_IE \ enable RC5_Int
38855 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38856 \ ******************************\
38857 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
38858 \ ******************************\
38859 \ %01 0001 0100 \ TAxCTL
38860 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
38861 \ -- \ ID divided by 1
38862 \ -- \ MC MODE = up to TAxCCRn
38863 \ - \ TACLR clear timer count
38866 \ ------------------------------\
38867 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
38868 \ ------------------------------\
38870 \ --- \ TAIDEX pre divisor
38871 \ ------------------------------\
38872 \ %0000 0000 0000 0101 \ TAxCCR0
38873 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
38874 \ ------------------------------\
38875 \ %0000 0000 0001 0000 \ TAxCCTL0
38876 \ - \ CAP capture/compare mode = compare
38879 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
38880 \ ------------------------------\
38881 \ define LPM mode for ACCEPT \
38882 \ ------------------------------\
38883 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
38884 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38885 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38886 \ ------------------------------\
38888 \ ------------------------------\
38890 \ ------------------------------\
38891 #1000 20_US \ 1- wait 20 ms
38892 %011 TOP_LCD \ 2- send DB5=DB4=1
38893 #205 20_US \ 3- wait 4,1 ms
38894 %011 TOP_LCD \ 4- send again DB5=DB4=1
38895 #5 20_US \ 5- wait 0,1 ms
38896 %011 TOP_LCD \ 6- send again again DB5=DB4=1
38897 #2 20_US \ wait 40 us = LCD cycle
38898 %010 TOP_LCD \ 7- send DB5=1 DB4=0
38899 #2 20_US \ wait 40 us = LCD cycle
38900 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38901 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38902 LCD_CLEAR \ 10- "LCD_Clear"
38903 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38904 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38905 LCD_CLEAR \ 10- "LCD_Clear"
38906 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38907 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38908 CR ." I love you" \ display message on LCD
38909 ['] CR >BODY IS CR \ CR executes its default value
38910 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
38911 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
38914 \ ------------------------------\
38916 \ ------------------------------\
38917 CODE START \ this routine replaces WARM and COLD default values by these of this application.
38918 \ ------------------------------\
38919 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
38920 0= IF \ if not done, customizes MARKER_DOES
38921 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
38922 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
38923 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
38924 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
38925 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
38926 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
38927 MOV #RC5_INT,&IR_VEC \ init interrupt vector
38928 MOV #INI_R2L,PC \ then execute new INI_APP, without return
38932 \ ------------------------------\
38935 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
38937 MARKER {RC5TOLCD} \ restore the state before MARKER definition
38938 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
38939 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
38940 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
38941 \ {RC5TOLCD}+14: make room to save previous IR_VEC
38943 [UNDEFINED] CONSTANT [IF]
38944 \ https://forth-standard.org/standard/core/CONSTANT
38945 \ CONSTANT <name> n -- define a Forth CONSTANT
38949 MOV TOS,-2(W) \ PFA = n
38956 [UNDEFINED] STATE [IF]
38957 \ https://forth-standard.org/standard/core/STATE
38958 \ STATE -- a-addr holds compiler state
38959 STATEADR CONSTANT STATE
38963 \ https://forth-standard.org/standard/core/Equal
38964 \ = x1 x2 -- flag test x1=x2
38971 XOR #-1,TOS \ 1 flag Z = 1
38976 [UNDEFINED] IF [IF] \ define IF and THEN
38977 \ https://forth-standard.org/standard/core/IF
38978 \ IF -- IFadr initialize conditional forward branch
38979 CODE IF \ immediate
38982 MOV &DP,TOS \ -- HERE
38983 ADD #4,&DP \ compile one word, reserve one word
38984 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
38985 ADD #2,TOS \ -- HERE+2=IFadr
38989 \ https://forth-standard.org/standard/core/THEN
38990 \ THEN IFadr -- resolve forward branch
38991 CODE THEN \ immediate
38992 MOV &DP,0(TOS) \ -- IFadr
38998 [UNDEFINED] ELSE [IF]
38999 \ https://forth-standard.org/standard/core/ELSE
39000 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
39001 CODE ELSE \ immediate
39002 ADD #4,&DP \ make room to compile two words
39003 MOV &DP,W \ W=HERE+4
39005 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
39007 MOV W,TOS \ -- ELSEadr
39012 [UNDEFINED] IS [IF] \ define DEFER! and IS
39014 \ https://forth-standard.org/standard/core/DEFERStore
39015 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
39016 CODE DEFER! \ xt2 xt1 --
39017 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
39022 \ https://forth-standard.org/standard/core/IS
39025 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
39026 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
39027 \ or in a definition : ... ['] U. IS DISPLAY ...
39028 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
39030 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
39034 IF POSTPONE ['] POSTPONE DEFER!
39040 [UNDEFINED] >BODY [IF]
39041 \ https://forth-standard.org/standard/core/toBODY
39042 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
39049 \ CODE 20uS \ n -- 8MHz version
39050 \ BEGIN \ 4 + 16 ~ loop
39051 \ MOV #39,rDOCON \ 39
39058 \ MOV #XDOCON,rDOCON \ 2
39063 CODE 20_US \ n -- n * 20 us
39064 BEGIN \ here we presume that LCD_TIM_IFG = 1...
39066 BIT #1,&LCD_TIM_CTL \ 3
39067 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
39068 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
39070 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
39075 CODE TOP_LCD \ LCD Sample
39076 \ \ if write : %xxxx_WWWW --
39077 \ \ if read : -- %0000_RRRR
39078 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39079 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39080 0= IF \ write LCD bits pattern
39081 AND.B #LCD_DB,TOS \
39082 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39083 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39086 THEN \ read LCD bits pattern
39089 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39090 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39091 AND.B #LCD_DB,TOS \
39095 CODE LCD_WRC \ char -- Write Char
39096 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39098 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
39099 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
39100 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39101 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39102 COLON \ high level word starts here
39103 TOP_LCD 2 20_US \ write high nibble first
39107 CODE LCD_WRF \ func -- Write Fonction
39108 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39112 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
39113 : LCD_HOME $02 LCD_WRF 100 20_us ;
39115 \ [UNDEFINED] OR [IF]
39117 \ \ https://forth-standard.org/standard/core/OR
39118 \ \ C OR x1 x2 -- x3 logical OR
39126 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
39127 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
39128 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
39129 \ : LCD_FN_SET $20 OR LCD_WrF ;
39130 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
39131 \ : LCD_GOTO $80 OR LCD_WrF ;
39134 \ CODE LCD_RDS \ -- status Read Status
39135 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39136 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39137 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39138 \ COLON \ starts a FORTH word
39139 \ TOP_LCD 2 20_us \ -- %0000_HHHH
39140 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
39141 \ HI2LO \ switch from FORTH to assembler
39142 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
39143 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
39144 \ MOV @RSP+,IP \ restore IP saved by COLON
39148 \ CODE LCD_RDC \ -- char Read Char
39149 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39154 \ ******************************\
39155 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39156 \ ******************************\
39157 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
39158 BIT.B #SW2,&SW2_IN \ test switch S2
39159 0= IF \ case of switch S2 pressed
39160 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
39162 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
39165 BIT.B #SW1,&SW1_IN \ test switch S1 input
39166 0= IF \ case of Switch S1 pressed
39167 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
39169 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
39176 \ ******************************\
39177 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
39178 \ ******************************\
39179 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39180 \ ******************************\
39181 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39182 \ \ SMclock = 8|16|24 MHz
39183 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
39184 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
39185 \ \ SR(9)=new Toggle bit memory (ADD on)
39186 \ ******************************\
39187 \ RC5_FirstStartBitHalfCycle: \
39188 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
39189 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
39190 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
39192 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
39193 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
39195 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
39196 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
39198 MOV #1778,X \ RC5_Period * 1us
39199 MOV #14,W \ count of loop
39201 \ ******************************\
39202 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
39203 \ ******************************\ |
39204 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
39205 \ RC5_Compute_3/4_Period: \ |
39206 RRUM #1,X \ X=1/2 cycle |
39209 ADD X,Y \ Y=3/4 cycle
39210 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
39212 \ ******************************\
39213 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
39214 \ ******************************\
39215 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39216 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
39217 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39218 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39219 SUB #1,W \ decrement count loop
39220 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
39221 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39222 0<> WHILE \ ----> out of loop ----+
39223 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
39225 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
39226 CMP Y,X \ 1 | cycle time out of bound ?
39227 U>= IF \ 2 ^ | yes:
39228 BIC #$30,&RC5_TIM_CTL \ | | stop timer
39229 GOTO FW1 \ | | quit on truncated RC5 message
39231 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
39233 REPEAT \ ----> loop back --+ | with X = new RC5_period value
39234 \ ******************************\ |
39235 \ RC5_SampleEndOf: \ <---------------------+
39236 \ ******************************\
39237 BIC #$30,&RC5_TIM_CTL \ stop timer
39238 \ ******************************\
39239 \ RC5_ComputeNewRC5word \
39240 \ ******************************\
39241 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
39242 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
39243 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
39244 \ ******************************\
39245 \ RC5_ComputeC6bit \
39246 \ ******************************\
39247 BIT #BIT14,T \ test /C6 bit in T
39248 0= IF BIS #BIT6,X \ set C6 bit in X
39249 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
39250 \ ******************************\
39251 \ RC5_CommandByteIsDone \ -- BASE RC5_code
39252 \ ******************************\
39253 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
39254 \ ******************************\
39255 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
39256 XOR @RSP,T \ (new XOR old) Toggle bits
39257 BIT #UF10,T \ repeated RC5_command ?
39258 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
39259 XOR #UF10,0(RSP) \ 5 toggle bit memory
39260 \ ******************************\
39261 \ Display IR_RC5 code \
39262 \ ******************************\
39263 SUB #8,PSP \ TOS -- x x x x TOS
39264 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
39265 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
39266 MOV #$10,&BASEADR \ set hexadecimal base
39267 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
39268 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
39269 LO2HI \ switch from assembler to FORTH
39270 LCD_CLEAR \ set LCD cursor at home
39271 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
39272 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
39273 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
39274 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
39275 HI2LO \ -- switch from FORTH to assembler
39276 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
39277 MOV @PSP+,TOS \ -- TOS
39279 MOV @RSP+,SR \ restore SR flags
39280 BIC #%1111_1000,SR \ but force CPU Active Mode
39281 RET \ (instead of RETI)
39285 \ ------------------------------\
39286 HDNCODE STOP_R2L \ define new STOP_APP
39287 \ ------------------------------\
39288 CMP #RET_ADR,&{RC5TOLCD}+8 \
39289 0<> IF \ if previous START executing
39290 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
39291 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
39292 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
39293 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
39294 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
39295 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
39296 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
39297 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
39298 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
39299 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
39304 \ ------------------------------\
39306 \ ------------------------------\
39307 BW1 \ <-- INI_R2L for some events
39309 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
39311 ." RC5toLCD is removed,"
39312 ." type START to restart"
39315 \ ------------------------------\
39317 \ ------------------------------\
39318 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
39319 \ ------------------------------\
39321 \ ------------------------------\
39322 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
39323 \ ------------------------------\
39324 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
39325 \ ------------------------------\
39326 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
39327 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
39329 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
39330 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
39332 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
39333 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
39334 \ CMP #4,TOS \ hardware RST
39335 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
39336 \ CMP #2,TOS \ Power_ON event
39337 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
39339 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
39341 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
39343 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
39344 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
39345 \ ------------------------------\
39346 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
39347 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39348 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39349 \ -- \ID input divider \ 10 = /4
39350 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
39351 \ - \TBCLR TimerB Clear
39354 \ -------------------------------\
39355 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39356 \ -- \CM Capture Mode
39361 \ --- \OUTMOD \ 011 = set/reset
39367 \ -------------------------------\
39369 \ -------------------------------\
39371 \ ------------------------------\
39372 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
39373 \ ------------------------------\
39374 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
39375 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
39376 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
39377 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
39379 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
39380 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
39382 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
39383 \ ------------------------------\
39384 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
39385 \ ------------------------------\
39386 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
39387 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
39388 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39389 \ ------------------------------\
39390 BIS.B #LCDVo,&LCDVo_DIR \
39391 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
39392 \ ------------------------------\
39393 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39394 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39395 \ ------------------------------\
39396 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39397 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39398 \ ******************************\
39400 \ ******************************\
39401 BIS.B #RC5,&IR_IE \ enable RC5_Int
39402 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39403 \ ******************************\
39404 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
39405 \ ******************************\
39406 \ %01 0001 0100 \ TAxCTL
39407 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
39408 \ -- \ ID divided by 1
39409 \ -- \ MC MODE = up to TAxCCRn
39410 \ - \ TACLR clear timer count
39413 \ ------------------------------\
39414 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
39415 \ ------------------------------\
39417 \ --- \ TAIDEX pre divisor
39418 \ ------------------------------\
39419 \ %0000 0000 0000 0101 \ TAxCCR0
39420 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
39421 \ ------------------------------\
39422 \ %0000 0000 0001 0000 \ TAxCCTL0
39423 \ - \ CAP capture/compare mode = compare
39426 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
39427 \ ------------------------------\
39428 \ define LPM mode for ACCEPT \
39429 \ ------------------------------\
39430 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
39431 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39432 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39433 \ ------------------------------\
39435 \ ------------------------------\
39437 \ ------------------------------\
39438 #1000 20_US \ 1- wait 20 ms
39439 %011 TOP_LCD \ 2- send DB5=DB4=1
39440 #205 20_US \ 3- wait 4,1 ms
39441 %011 TOP_LCD \ 4- send again DB5=DB4=1
39442 #5 20_US \ 5- wait 0,1 ms
39443 %011 TOP_LCD \ 6- send again again DB5=DB4=1
39444 #2 20_US \ wait 40 us = LCD cycle
39445 %010 TOP_LCD \ 7- send DB5=1 DB4=0
39446 #2 20_US \ wait 40 us = LCD cycle
39447 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39448 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39449 LCD_CLEAR \ 10- "LCD_Clear"
39450 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39451 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39452 LCD_CLEAR \ 10- "LCD_Clear"
39453 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
39454 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
39455 CR ." I love you" \ display message on LCD
39456 ['] CR >BODY IS CR \ CR executes its default value
39457 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
39458 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
39461 \ ------------------------------\
39463 \ ------------------------------\
39464 CODE START \ this routine replaces WARM and COLD default values by these of this application.
39465 \ ------------------------------\
39466 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
39467 0= IF \ if not done, customizes MARKER_DOES
39468 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
39469 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
39470 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
39471 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
39472 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
39473 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
39474 MOV #RC5_INT,&IR_VEC \ init interrupt vector
39475 MOV #INI_R2L,PC \ then execute new INI_APP, without return
39479 \ ------------------------------\
39482 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
39484 MARKER {RC5TOLCD} \ restore the state before MARKER definition
39485 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
39486 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
39487 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
39488 \ {RC5TOLCD}+14: make room to save previous IR_VEC
39490 [UNDEFINED] CONSTANT [IF]
39491 \ https://forth-standard.org/standard/core/CONSTANT
39492 \ CONSTANT <name> n -- define a Forth CONSTANT
39496 MOV TOS,-2(W) \ PFA = n
39503 [UNDEFINED] STATE [IF]
39504 \ https://forth-standard.org/standard/core/STATE
39505 \ STATE -- a-addr holds compiler state
39506 STATEADR CONSTANT STATE
39510 \ https://forth-standard.org/standard/core/Equal
39511 \ = x1 x2 -- flag test x1=x2
39518 XOR #-1,TOS \ 1 flag Z = 1
39523 [UNDEFINED] IF [IF] \ define IF and THEN
39524 \ https://forth-standard.org/standard/core/IF
39525 \ IF -- IFadr initialize conditional forward branch
39526 CODE IF \ immediate
39529 MOV &DP,TOS \ -- HERE
39530 ADD #4,&DP \ compile one word, reserve one word
39531 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
39532 ADD #2,TOS \ -- HERE+2=IFadr
39536 \ https://forth-standard.org/standard/core/THEN
39537 \ THEN IFadr -- resolve forward branch
39538 CODE THEN \ immediate
39539 MOV &DP,0(TOS) \ -- IFadr
39545 [UNDEFINED] ELSE [IF]
39546 \ https://forth-standard.org/standard/core/ELSE
39547 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
39548 CODE ELSE \ immediate
39549 ADD #4,&DP \ make room to compile two words
39550 MOV &DP,W \ W=HERE+4
39552 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
39554 MOV W,TOS \ -- ELSEadr
39559 [UNDEFINED] IS [IF] \ define DEFER! and IS
39561 \ https://forth-standard.org/standard/core/DEFERStore
39562 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
39563 CODE DEFER! \ xt2 xt1 --
39564 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
39569 \ https://forth-standard.org/standard/core/IS
39572 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
39573 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
39574 \ or in a definition : ... ['] U. IS DISPLAY ...
39575 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
39577 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
39581 IF POSTPONE ['] POSTPONE DEFER!
39587 [UNDEFINED] >BODY [IF]
39588 \ https://forth-standard.org/standard/core/toBODY
39589 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
39596 \ CODE 20uS \ n -- 8MHz version
39597 \ BEGIN \ 4 + 16 ~ loop
39598 \ MOV #39,rDOCON \ 39
39605 \ MOV #XDOCON,rDOCON \ 2
39610 CODE 20_US \ n -- n * 20 us
39611 BEGIN \ here we presume that LCD_TIM_IFG = 1...
39613 BIT #1,&LCD_TIM_CTL \ 3
39614 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
39615 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
39617 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
39622 CODE TOP_LCD \ LCD Sample
39623 \ \ if write : %xxxx_WWWW --
39624 \ \ if read : -- %0000_RRRR
39625 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39626 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39627 0= IF \ write LCD bits pattern
39628 AND.B #LCD_DB,TOS \
39629 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39630 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39633 THEN \ read LCD bits pattern
39636 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39637 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39638 AND.B #LCD_DB,TOS \
39642 CODE LCD_WRC \ char -- Write Char
39643 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39645 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
39646 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
39647 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39648 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39649 COLON \ high level word starts here
39650 TOP_LCD 2 20_US \ write high nibble first
39654 CODE LCD_WRF \ func -- Write Fonction
39655 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39659 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
39660 : LCD_HOME $02 LCD_WRF 100 20_us ;
39662 \ [UNDEFINED] OR [IF]
39664 \ \ https://forth-standard.org/standard/core/OR
39665 \ \ C OR x1 x2 -- x3 logical OR
39673 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
39674 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
39675 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
39676 \ : LCD_FN_SET $20 OR LCD_WrF ;
39677 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
39678 \ : LCD_GOTO $80 OR LCD_WrF ;
39681 \ CODE LCD_RDS \ -- status Read Status
39682 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39683 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39684 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39685 \ COLON \ starts a FORTH word
39686 \ TOP_LCD 2 20_us \ -- %0000_HHHH
39687 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
39688 \ HI2LO \ switch from FORTH to assembler
39689 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
39690 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
39691 \ MOV @RSP+,IP \ restore IP saved by COLON
39695 \ CODE LCD_RDC \ -- char Read Char
39696 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39701 \ ******************************\
39702 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39703 \ ******************************\
39704 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
39705 BIT.B #SW2,&SW2_IN \ test switch S2
39706 0= IF \ case of switch S2 pressed
39707 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
39709 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
39712 BIT.B #SW1,&SW1_IN \ test switch S1 input
39713 0= IF \ case of Switch S1 pressed
39714 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
39716 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
39723 \ ******************************\
39724 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
39725 \ ******************************\
39726 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39727 \ ******************************\
39728 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39729 \ \ SMclock = 8|16|24 MHz
39730 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
39731 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
39732 \ \ SR(9)=new Toggle bit memory (ADD on)
39733 \ ******************************\
39734 \ RC5_FirstStartBitHalfCycle: \
39735 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
39736 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
39737 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
39739 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
39740 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
39742 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
39743 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
39745 MOV #1778,X \ RC5_Period * 1us
39746 MOV #14,W \ count of loop
39748 \ ******************************\
39749 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
39750 \ ******************************\ |
39751 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
39752 \ RC5_Compute_3/4_Period: \ |
39753 RRUM #1,X \ X=1/2 cycle |
39756 ADD X,Y \ Y=3/4 cycle
39757 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
39759 \ ******************************\
39760 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
39761 \ ******************************\
39762 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39763 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
39764 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39765 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39766 SUB #1,W \ decrement count loop
39767 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
39768 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39769 0<> WHILE \ ----> out of loop ----+
39770 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
39772 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
39773 CMP Y,X \ 1 | cycle time out of bound ?
39774 U>= IF \ 2 ^ | yes:
39775 BIC #$30,&RC5_TIM_CTL \ | | stop timer
39776 GOTO FW1 \ | | quit on truncated RC5 message
39778 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
39780 REPEAT \ ----> loop back --+ | with X = new RC5_period value
39781 \ ******************************\ |
39782 \ RC5_SampleEndOf: \ <---------------------+
39783 \ ******************************\
39784 BIC #$30,&RC5_TIM_CTL \ stop timer
39785 \ ******************************\
39786 \ RC5_ComputeNewRC5word \
39787 \ ******************************\
39788 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
39789 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
39790 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
39791 \ ******************************\
39792 \ RC5_ComputeC6bit \
39793 \ ******************************\
39794 BIT #BIT14,T \ test /C6 bit in T
39795 0= IF BIS #BIT6,X \ set C6 bit in X
39796 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
39797 \ ******************************\
39798 \ RC5_CommandByteIsDone \ -- BASE RC5_code
39799 \ ******************************\
39800 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
39801 \ ******************************\
39802 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
39803 XOR @RSP,T \ (new XOR old) Toggle bits
39804 BIT #UF10,T \ repeated RC5_command ?
39805 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
39806 XOR #UF10,0(RSP) \ 5 toggle bit memory
39807 \ ******************************\
39808 \ Display IR_RC5 code \
39809 \ ******************************\
39810 SUB #8,PSP \ TOS -- x x x x TOS
39811 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
39812 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
39813 MOV #$10,&BASEADR \ set hexadecimal base
39814 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
39815 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
39816 LO2HI \ switch from assembler to FORTH
39817 LCD_CLEAR \ set LCD cursor at home
39818 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
39819 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
39820 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
39821 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
39822 HI2LO \ -- switch from FORTH to assembler
39823 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
39824 MOV @PSP+,TOS \ -- TOS
39826 MOV @RSP+,SR \ restore SR flags
39827 BIC #%1111_1000,SR \ but force CPU Active Mode
39828 RET \ (instead of RETI)
39832 \ ------------------------------\
39833 HDNCODE STOP_R2L \ define new STOP_APP
39834 \ ------------------------------\
39835 CMP #RET_ADR,&{RC5TOLCD}+8 \
39836 0<> IF \ if previous START executing
39837 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
39838 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
39839 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
39840 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
39841 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
39842 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
39843 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
39844 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
39845 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
39846 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
39851 \ ------------------------------\
39853 \ ------------------------------\
39854 BW1 \ <-- INI_R2L for some events
39856 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
39858 ." RC5toLCD is removed,"
39859 ." type START to restart"
39862 \ ------------------------------\
39864 \ ------------------------------\
39865 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
39866 \ ------------------------------\
39868 \ ------------------------------\
39869 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
39870 \ ------------------------------\
39871 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
39872 \ ------------------------------\
39873 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
39874 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
39876 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
39877 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
39879 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
39880 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
39881 \ CMP #4,TOS \ hardware RST
39882 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
39883 \ CMP #2,TOS \ Power_ON event
39884 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
39886 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
39888 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
39890 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
39891 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
39892 \ ------------------------------\
39893 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
39894 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39895 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39896 \ -- \ID input divider \ 10 = /4
39897 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
39898 \ - \TBCLR TimerB Clear
39901 \ -------------------------------\
39902 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39903 \ -- \CM Capture Mode
39908 \ --- \OUTMOD \ 011 = set/reset
39914 \ -------------------------------\
39916 \ -------------------------------\
39918 \ ------------------------------\
39919 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
39920 \ ------------------------------\
39921 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
39922 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
39923 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
39924 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
39926 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
39927 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
39929 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
39930 \ ------------------------------\
39931 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
39932 \ ------------------------------\
39933 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
39934 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
39935 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39936 \ ------------------------------\
39937 BIS.B #LCDVo,&LCDVo_DIR \
39938 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
39939 \ ------------------------------\
39940 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39941 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39942 \ ------------------------------\
39943 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39944 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39945 \ ******************************\
39947 \ ******************************\
39948 BIS.B #RC5,&IR_IE \ enable RC5_Int
39949 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39950 \ ******************************\
39951 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
39952 \ ******************************\
39953 \ %01 0001 0100 \ TAxCTL
39954 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
39955 \ -- \ ID divided by 1
39956 \ -- \ MC MODE = up to TAxCCRn
39957 \ - \ TACLR clear timer count
39960 \ ------------------------------\
39961 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
39962 \ ------------------------------\
39964 \ --- \ TAIDEX pre divisor
39965 \ ------------------------------\
39966 \ %0000 0000 0000 0101 \ TAxCCR0
39967 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
39968 \ ------------------------------\
39969 \ %0000 0000 0001 0000 \ TAxCCTL0
39970 \ - \ CAP capture/compare mode = compare
39973 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
39974 \ ------------------------------\
39975 \ define LPM mode for ACCEPT \
39976 \ ------------------------------\
39977 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
39978 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39979 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39980 \ ------------------------------\
39982 \ ------------------------------\
39984 \ ------------------------------\
39985 #1000 20_US \ 1- wait 20 ms
39986 %011 TOP_LCD \ 2- send DB5=DB4=1
39987 #205 20_US \ 3- wait 4,1 ms
39988 %011 TOP_LCD \ 4- send again DB5=DB4=1
39989 #5 20_US \ 5- wait 0,1 ms
39990 %011 TOP_LCD \ 6- send again again DB5=DB4=1
39991 #2 20_US \ wait 40 us = LCD cycle
39992 %010 TOP_LCD \ 7- send DB5=1 DB4=0
39993 #2 20_US \ wait 40 us = LCD cycle
39994 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39995 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39996 LCD_CLEAR \ 10- "LCD_Clear"
39997 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39998 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39999 LCD_CLEAR \ 10- "LCD_Clear"
40000 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40001 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40002 CR ." I love you" \ display message on LCD
40003 ['] CR >BODY IS CR \ CR executes its default value
40004 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
40005 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
40008 \ ------------------------------\
40010 \ ------------------------------\
40011 CODE START \ this routine replaces WARM and COLD default values by these of this application.
40012 \ ------------------------------\
40013 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
40014 0= IF \ if not done, customizes MARKER_DOES
40015 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
40016 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
40017 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
40018 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
40019 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
40020 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
40021 MOV #RC5_INT,&IR_VEC \ init interrupt vector
40022 MOV #INI_R2L,PC \ then execute new INI_APP, without return
40026 \ ------------------------------\
40029 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
40031 MARKER {RC5TOLCD} \ restore the state before MARKER definition
40032 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
40033 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
40034 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
40035 \ {RC5TOLCD}+14: make room to save previous IR_VEC
40037 [UNDEFINED] CONSTANT [IF]
40038 \ https://forth-standard.org/standard/core/CONSTANT
40039 \ CONSTANT <name> n -- define a Forth CONSTANT
40043 MOV TOS,-2(W) \ PFA = n
40050 [UNDEFINED] STATE [IF]
40051 \ https://forth-standard.org/standard/core/STATE
40052 \ STATE -- a-addr holds compiler state
40053 STATEADR CONSTANT STATE
40057 \ https://forth-standard.org/standard/core/Equal
40058 \ = x1 x2 -- flag test x1=x2
40065 XOR #-1,TOS \ 1 flag Z = 1
40070 [UNDEFINED] IF [IF] \ define IF and THEN
40071 \ https://forth-standard.org/standard/core/IF
40072 \ IF -- IFadr initialize conditional forward branch
40073 CODE IF \ immediate
40076 MOV &DP,TOS \ -- HERE
40077 ADD #4,&DP \ compile one word, reserve one word
40078 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
40079 ADD #2,TOS \ -- HERE+2=IFadr
40083 \ https://forth-standard.org/standard/core/THEN
40084 \ THEN IFadr -- resolve forward branch
40085 CODE THEN \ immediate
40086 MOV &DP,0(TOS) \ -- IFadr
40092 [UNDEFINED] ELSE [IF]
40093 \ https://forth-standard.org/standard/core/ELSE
40094 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
40095 CODE ELSE \ immediate
40096 ADD #4,&DP \ make room to compile two words
40097 MOV &DP,W \ W=HERE+4
40099 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
40101 MOV W,TOS \ -- ELSEadr
40106 [UNDEFINED] IS [IF] \ define DEFER! and IS
40108 \ https://forth-standard.org/standard/core/DEFERStore
40109 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
40110 CODE DEFER! \ xt2 xt1 --
40111 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
40116 \ https://forth-standard.org/standard/core/IS
40119 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
40120 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
40121 \ or in a definition : ... ['] U. IS DISPLAY ...
40122 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
40124 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
40128 IF POSTPONE ['] POSTPONE DEFER!
40134 [UNDEFINED] >BODY [IF]
40135 \ https://forth-standard.org/standard/core/toBODY
40136 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
40143 \ CODE 20uS \ n -- 8MHz version
40144 \ BEGIN \ 4 + 16 ~ loop
40145 \ MOV #39,rDOCON \ 39
40152 \ MOV #XDOCON,rDOCON \ 2
40157 CODE 20_US \ n -- n * 20 us
40158 BEGIN \ here we presume that LCD_TIM_IFG = 1...
40160 BIT #1,&LCD_TIM_CTL \ 3
40161 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
40162 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
40164 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
40169 CODE TOP_LCD \ LCD Sample
40170 \ \ if write : %xxxx_WWWW --
40171 \ \ if read : -- %0000_RRRR
40172 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40173 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40174 0= IF \ write LCD bits pattern
40175 AND.B #LCD_DB,TOS \
40176 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40177 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40180 THEN \ read LCD bits pattern
40183 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40184 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40185 AND.B #LCD_DB,TOS \
40189 CODE LCD_WRC \ char -- Write Char
40190 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40192 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
40193 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
40194 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40195 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40196 COLON \ high level word starts here
40197 TOP_LCD 2 20_US \ write high nibble first
40201 CODE LCD_WRF \ func -- Write Fonction
40202 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40206 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
40207 : LCD_HOME $02 LCD_WRF 100 20_us ;
40209 \ [UNDEFINED] OR [IF]
40211 \ \ https://forth-standard.org/standard/core/OR
40212 \ \ C OR x1 x2 -- x3 logical OR
40220 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
40221 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
40222 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
40223 \ : LCD_FN_SET $20 OR LCD_WrF ;
40224 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
40225 \ : LCD_GOTO $80 OR LCD_WrF ;
40228 \ CODE LCD_RDS \ -- status Read Status
40229 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40230 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40231 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40232 \ COLON \ starts a FORTH word
40233 \ TOP_LCD 2 20_us \ -- %0000_HHHH
40234 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
40235 \ HI2LO \ switch from FORTH to assembler
40236 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
40237 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
40238 \ MOV @RSP+,IP \ restore IP saved by COLON
40242 \ CODE LCD_RDC \ -- char Read Char
40243 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40248 \ ******************************\
40249 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40250 \ ******************************\
40251 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
40252 BIT.B #SW2,&SW2_IN \ test switch S2
40253 0= IF \ case of switch S2 pressed
40254 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
40256 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
40259 BIT.B #SW1,&SW1_IN \ test switch S1 input
40260 0= IF \ case of Switch S1 pressed
40261 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
40263 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
40270 \ ******************************\
40271 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
40272 \ ******************************\
40273 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40274 \ ******************************\
40275 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40276 \ \ SMclock = 8|16|24 MHz
40277 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
40278 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
40279 \ \ SR(9)=new Toggle bit memory (ADD on)
40280 \ ******************************\
40281 \ RC5_FirstStartBitHalfCycle: \
40282 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
40283 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
40284 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
40286 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
40287 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
40289 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
40290 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
40292 MOV #1778,X \ RC5_Period * 1us
40293 MOV #14,W \ count of loop
40295 \ ******************************\
40296 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
40297 \ ******************************\ |
40298 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
40299 \ RC5_Compute_3/4_Period: \ |
40300 RRUM #1,X \ X=1/2 cycle |
40303 ADD X,Y \ Y=3/4 cycle
40304 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
40306 \ ******************************\
40307 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
40308 \ ******************************\
40309 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40310 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
40311 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40312 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40313 SUB #1,W \ decrement count loop
40314 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
40315 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40316 0<> WHILE \ ----> out of loop ----+
40317 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
40319 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
40320 CMP Y,X \ 1 | cycle time out of bound ?
40321 U>= IF \ 2 ^ | yes:
40322 BIC #$30,&RC5_TIM_CTL \ | | stop timer
40323 GOTO FW1 \ | | quit on truncated RC5 message
40325 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
40327 REPEAT \ ----> loop back --+ | with X = new RC5_period value
40328 \ ******************************\ |
40329 \ RC5_SampleEndOf: \ <---------------------+
40330 \ ******************************\
40331 BIC #$30,&RC5_TIM_CTL \ stop timer
40332 \ ******************************\
40333 \ RC5_ComputeNewRC5word \
40334 \ ******************************\
40335 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
40336 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
40337 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
40338 \ ******************************\
40339 \ RC5_ComputeC6bit \
40340 \ ******************************\
40341 BIT #BIT14,T \ test /C6 bit in T
40342 0= IF BIS #BIT6,X \ set C6 bit in X
40343 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
40344 \ ******************************\
40345 \ RC5_CommandByteIsDone \ -- BASE RC5_code
40346 \ ******************************\
40347 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
40348 \ ******************************\
40349 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
40350 XOR @RSP,T \ (new XOR old) Toggle bits
40351 BIT #UF10,T \ repeated RC5_command ?
40352 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
40353 XOR #UF10,0(RSP) \ 5 toggle bit memory
40354 \ ******************************\
40355 \ Display IR_RC5 code \
40356 \ ******************************\
40357 SUB #8,PSP \ TOS -- x x x x TOS
40358 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
40359 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
40360 MOV #$10,&BASEADR \ set hexadecimal base
40361 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
40362 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
40363 LO2HI \ switch from assembler to FORTH
40364 LCD_CLEAR \ set LCD cursor at home
40365 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
40366 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
40367 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
40368 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
40369 HI2LO \ -- switch from FORTH to assembler
40370 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
40371 MOV @PSP+,TOS \ -- TOS
40373 MOV @RSP+,SR \ restore SR flags
40374 BIC #%1111_1000,SR \ but force CPU Active Mode
40375 RET \ (instead of RETI)
40379 \ ------------------------------\
40380 HDNCODE STOP_R2L \ define new STOP_APP
40381 \ ------------------------------\
40382 CMP #RET_ADR,&{RC5TOLCD}+8 \
40383 0<> IF \ if previous START executing
40384 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
40385 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
40386 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
40387 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
40388 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
40389 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
40390 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
40391 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
40392 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
40393 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
40398 \ ------------------------------\
40400 \ ------------------------------\
40401 BW1 \ <-- INI_R2L for some events
40403 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
40405 ." RC5toLCD is removed,"
40406 ." type START to restart"
40409 \ ------------------------------\
40411 \ ------------------------------\
40412 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
40413 \ ------------------------------\
40415 \ ------------------------------\
40416 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
40417 \ ------------------------------\
40418 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
40419 \ ------------------------------\
40420 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
40421 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
40423 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
40424 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
40426 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
40427 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
40428 \ CMP #4,TOS \ hardware RST
40429 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
40430 \ CMP #2,TOS \ Power_ON event
40431 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
40433 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
40435 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
40437 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
40438 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
40439 \ ------------------------------\
40440 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
40441 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40442 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40443 \ -- \ID input divider \ 10 = /4
40444 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
40445 \ - \TBCLR TimerB Clear
40448 \ -------------------------------\
40449 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40450 \ -- \CM Capture Mode
40455 \ --- \OUTMOD \ 011 = set/reset
40461 \ -------------------------------\
40463 \ -------------------------------\
40465 \ ------------------------------\
40466 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
40467 \ ------------------------------\
40468 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
40469 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
40470 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
40471 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
40473 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
40474 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
40476 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
40477 \ ------------------------------\
40478 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
40479 \ ------------------------------\
40480 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
40481 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
40482 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40483 \ ------------------------------\
40484 BIS.B #LCDVo,&LCDVo_DIR \
40485 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
40486 \ ------------------------------\
40487 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40488 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40489 \ ------------------------------\
40490 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40491 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40492 \ ******************************\
40494 \ ******************************\
40495 BIS.B #RC5,&IR_IE \ enable RC5_Int
40496 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40497 \ ******************************\
40498 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
40499 \ ******************************\
40500 \ %01 0001 0100 \ TAxCTL
40501 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
40502 \ -- \ ID divided by 1
40503 \ -- \ MC MODE = up to TAxCCRn
40504 \ - \ TACLR clear timer count
40507 \ ------------------------------\
40508 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
40509 \ ------------------------------\
40511 \ --- \ TAIDEX pre divisor
40512 \ ------------------------------\
40513 \ %0000 0000 0000 0101 \ TAxCCR0
40514 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
40515 \ ------------------------------\
40516 \ %0000 0000 0001 0000 \ TAxCCTL0
40517 \ - \ CAP capture/compare mode = compare
40520 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
40521 \ ------------------------------\
40522 \ define LPM mode for ACCEPT \
40523 \ ------------------------------\
40524 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
40525 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40526 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40527 \ ------------------------------\
40529 \ ------------------------------\
40531 \ ------------------------------\
40532 #1000 20_US \ 1- wait 20 ms
40533 %011 TOP_LCD \ 2- send DB5=DB4=1
40534 #205 20_US \ 3- wait 4,1 ms
40535 %011 TOP_LCD \ 4- send again DB5=DB4=1
40536 #5 20_US \ 5- wait 0,1 ms
40537 %011 TOP_LCD \ 6- send again again DB5=DB4=1
40538 #2 20_US \ wait 40 us = LCD cycle
40539 %010 TOP_LCD \ 7- send DB5=1 DB4=0
40540 #2 20_US \ wait 40 us = LCD cycle
40541 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40542 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40543 LCD_CLEAR \ 10- "LCD_Clear"
40544 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40545 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40546 LCD_CLEAR \ 10- "LCD_Clear"
40547 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40548 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40549 CR ." I love you" \ display message on LCD
40550 ['] CR >BODY IS CR \ CR executes its default value
40551 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
40552 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
40555 \ ------------------------------\
40557 \ ------------------------------\
40558 CODE START \ this routine replaces WARM and COLD default values by these of this application.
40559 \ ------------------------------\
40560 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
40561 0= IF \ if not done, customizes MARKER_DOES
40562 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
40563 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
40564 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
40565 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
40566 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
40567 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
40568 MOV #RC5_INT,&IR_VEC \ init interrupt vector
40569 MOV #INI_R2L,PC \ then execute new INI_APP, without return
40573 \ ------------------------------\
40576 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
40578 MARKER {RC5TOLCD} \ restore the state before MARKER definition
40579 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
40580 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
40581 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
40582 \ {RC5TOLCD}+14: make room to save previous IR_VEC
40584 [UNDEFINED] CONSTANT [IF]
40585 \ https://forth-standard.org/standard/core/CONSTANT
40586 \ CONSTANT <name> n -- define a Forth CONSTANT
40590 MOV TOS,-2(W) \ PFA = n
40597 [UNDEFINED] STATE [IF]
40598 \ https://forth-standard.org/standard/core/STATE
40599 \ STATE -- a-addr holds compiler state
40600 STATEADR CONSTANT STATE
40604 \ https://forth-standard.org/standard/core/Equal
40605 \ = x1 x2 -- flag test x1=x2
40612 XOR #-1,TOS \ 1 flag Z = 1
40617 [UNDEFINED] IF [IF] \ define IF and THEN
40618 \ https://forth-standard.org/standard/core/IF
40619 \ IF -- IFadr initialize conditional forward branch
40620 CODE IF \ immediate
40623 MOV &DP,TOS \ -- HERE
40624 ADD #4,&DP \ compile one word, reserve one word
40625 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
40626 ADD #2,TOS \ -- HERE+2=IFadr
40630 \ https://forth-standard.org/standard/core/THEN
40631 \ THEN IFadr -- resolve forward branch
40632 CODE THEN \ immediate
40633 MOV &DP,0(TOS) \ -- IFadr
40639 [UNDEFINED] ELSE [IF]
40640 \ https://forth-standard.org/standard/core/ELSE
40641 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
40642 CODE ELSE \ immediate
40643 ADD #4,&DP \ make room to compile two words
40644 MOV &DP,W \ W=HERE+4
40646 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
40648 MOV W,TOS \ -- ELSEadr
40653 [UNDEFINED] IS [IF] \ define DEFER! and IS
40655 \ https://forth-standard.org/standard/core/DEFERStore
40656 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
40657 CODE DEFER! \ xt2 xt1 --
40658 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
40663 \ https://forth-standard.org/standard/core/IS
40666 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
40667 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
40668 \ or in a definition : ... ['] U. IS DISPLAY ...
40669 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
40671 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
40675 IF POSTPONE ['] POSTPONE DEFER!
40681 [UNDEFINED] >BODY [IF]
40682 \ https://forth-standard.org/standard/core/toBODY
40683 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
40690 \ CODE 20uS \ n -- 8MHz version
40691 \ BEGIN \ 4 + 16 ~ loop
40692 \ MOV #39,rDOCON \ 39
40699 \ MOV #XDOCON,rDOCON \ 2
40704 CODE 20_US \ n -- n * 20 us
40705 BEGIN \ here we presume that LCD_TIM_IFG = 1...
40707 BIT #1,&LCD_TIM_CTL \ 3
40708 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
40709 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
40711 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
40716 CODE TOP_LCD \ LCD Sample
40717 \ \ if write : %xxxx_WWWW --
40718 \ \ if read : -- %0000_RRRR
40719 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40720 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40721 0= IF \ write LCD bits pattern
40722 AND.B #LCD_DB,TOS \
40723 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40724 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40727 THEN \ read LCD bits pattern
40730 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40731 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40732 AND.B #LCD_DB,TOS \
40736 CODE LCD_WRC \ char -- Write Char
40737 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40739 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
40740 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
40741 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40742 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40743 COLON \ high level word starts here
40744 TOP_LCD 2 20_US \ write high nibble first
40748 CODE LCD_WRF \ func -- Write Fonction
40749 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40753 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
40754 : LCD_HOME $02 LCD_WRF 100 20_us ;
40756 \ [UNDEFINED] OR [IF]
40758 \ \ https://forth-standard.org/standard/core/OR
40759 \ \ C OR x1 x2 -- x3 logical OR
40767 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
40768 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
40769 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
40770 \ : LCD_FN_SET $20 OR LCD_WrF ;
40771 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
40772 \ : LCD_GOTO $80 OR LCD_WrF ;
40775 \ CODE LCD_RDS \ -- status Read Status
40776 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40777 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40778 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40779 \ COLON \ starts a FORTH word
40780 \ TOP_LCD 2 20_us \ -- %0000_HHHH
40781 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
40782 \ HI2LO \ switch from FORTH to assembler
40783 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
40784 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
40785 \ MOV @RSP+,IP \ restore IP saved by COLON
40789 \ CODE LCD_RDC \ -- char Read Char
40790 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40795 \ ******************************\
40796 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40797 \ ******************************\
40798 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
40799 BIT.B #SW2,&SW2_IN \ test switch S2
40800 0= IF \ case of switch S2 pressed
40801 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
40803 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
40806 BIT.B #SW1,&SW1_IN \ test switch S1 input
40807 0= IF \ case of Switch S1 pressed
40808 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
40810 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
40817 \ ******************************\
40818 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
40819 \ ******************************\
40820 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40821 \ ******************************\
40822 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40823 \ \ SMclock = 8|16|24 MHz
40824 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
40825 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
40826 \ \ SR(9)=new Toggle bit memory (ADD on)
40827 \ ******************************\
40828 \ RC5_FirstStartBitHalfCycle: \
40829 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
40830 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
40831 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
40833 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
40834 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
40836 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
40837 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
40839 MOV #1778,X \ RC5_Period * 1us
40840 MOV #14,W \ count of loop
40842 \ ******************************\
40843 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
40844 \ ******************************\ |
40845 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
40846 \ RC5_Compute_3/4_Period: \ |
40847 RRUM #1,X \ X=1/2 cycle |
40850 ADD X,Y \ Y=3/4 cycle
40851 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
40853 \ ******************************\
40854 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
40855 \ ******************************\
40856 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40857 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
40858 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40859 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40860 SUB #1,W \ decrement count loop
40861 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
40862 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40863 0<> WHILE \ ----> out of loop ----+
40864 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
40866 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
40867 CMP Y,X \ 1 | cycle time out of bound ?
40868 U>= IF \ 2 ^ | yes:
40869 BIC #$30,&RC5_TIM_CTL \ | | stop timer
40870 GOTO FW1 \ | | quit on truncated RC5 message
40872 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
40874 REPEAT \ ----> loop back --+ | with X = new RC5_period value
40875 \ ******************************\ |
40876 \ RC5_SampleEndOf: \ <---------------------+
40877 \ ******************************\
40878 BIC #$30,&RC5_TIM_CTL \ stop timer
40879 \ ******************************\
40880 \ RC5_ComputeNewRC5word \
40881 \ ******************************\
40882 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
40883 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
40884 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
40885 \ ******************************\
40886 \ RC5_ComputeC6bit \
40887 \ ******************************\
40888 BIT #BIT14,T \ test /C6 bit in T
40889 0= IF BIS #BIT6,X \ set C6 bit in X
40890 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
40891 \ ******************************\
40892 \ RC5_CommandByteIsDone \ -- BASE RC5_code
40893 \ ******************************\
40894 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
40895 \ ******************************\
40896 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
40897 XOR @RSP,T \ (new XOR old) Toggle bits
40898 BIT #UF10,T \ repeated RC5_command ?
40899 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
40900 XOR #UF10,0(RSP) \ 5 toggle bit memory
40901 \ ******************************\
40902 \ Display IR_RC5 code \
40903 \ ******************************\
40904 SUB #8,PSP \ TOS -- x x x x TOS
40905 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
40906 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
40907 MOV #$10,&BASEADR \ set hexadecimal base
40908 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
40909 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
40910 LO2HI \ switch from assembler to FORTH
40911 LCD_CLEAR \ set LCD cursor at home
40912 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
40913 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
40914 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
40915 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
40916 HI2LO \ -- switch from FORTH to assembler
40917 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
40918 MOV @PSP+,TOS \ -- TOS
40920 MOV @RSP+,SR \ restore SR flags
40921 BIC #%1111_1000,SR \ but force CPU Active Mode
40922 RET \ (instead of RETI)
40926 \ ------------------------------\
40927 HDNCODE STOP_R2L \ define new STOP_APP
40928 \ ------------------------------\
40929 CMP #RET_ADR,&{RC5TOLCD}+8 \
40930 0<> IF \ if previous START executing
40931 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
40932 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
40933 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
40934 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
40935 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
40936 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
40937 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
40938 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
40939 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
40940 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
40945 \ ------------------------------\
40947 \ ------------------------------\
40948 BW1 \ <-- INI_R2L for some events
40950 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
40952 ." RC5toLCD is removed,"
40953 ." type START to restart"
40956 \ ------------------------------\
40958 \ ------------------------------\
40959 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
40960 \ ------------------------------\
40962 \ ------------------------------\
40963 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
40964 \ ------------------------------\
40965 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
40966 \ ------------------------------\
40967 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
40968 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
40970 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
40971 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
40973 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
40974 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
40975 \ CMP #4,TOS \ hardware RST
40976 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
40977 \ CMP #2,TOS \ Power_ON event
40978 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
40980 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
40982 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
40984 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
40985 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
40986 \ ------------------------------\
40987 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
40988 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40989 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40990 \ -- \ID input divider \ 10 = /4
40991 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
40992 \ - \TBCLR TimerB Clear
40995 \ -------------------------------\
40996 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40997 \ -- \CM Capture Mode
41002 \ --- \OUTMOD \ 011 = set/reset
41008 \ -------------------------------\
41010 \ -------------------------------\
41012 \ ------------------------------\
41013 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
41014 \ ------------------------------\
41015 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
41016 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
41017 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
41018 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
41020 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
41021 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
41023 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
41024 \ ------------------------------\
41025 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
41026 \ ------------------------------\
41027 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
41028 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
41029 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41030 \ ------------------------------\
41031 BIS.B #LCDVo,&LCDVo_DIR \
41032 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
41033 \ ------------------------------\
41034 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41035 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41036 \ ------------------------------\
41037 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41038 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41039 \ ******************************\
41041 \ ******************************\
41042 BIS.B #RC5,&IR_IE \ enable RC5_Int
41043 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41044 \ ******************************\
41045 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
41046 \ ******************************\
41047 \ %01 0001 0100 \ TAxCTL
41048 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
41049 \ -- \ ID divided by 1
41050 \ -- \ MC MODE = up to TAxCCRn
41051 \ - \ TACLR clear timer count
41054 \ ------------------------------\
41055 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
41056 \ ------------------------------\
41058 \ --- \ TAIDEX pre divisor
41059 \ ------------------------------\
41060 \ %0000 0000 0000 0101 \ TAxCCR0
41061 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
41062 \ ------------------------------\
41063 \ %0000 0000 0001 0000 \ TAxCCTL0
41064 \ - \ CAP capture/compare mode = compare
41067 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
41068 \ ------------------------------\
41069 \ define LPM mode for ACCEPT \
41070 \ ------------------------------\
41071 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
41072 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41073 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41074 \ ------------------------------\
41076 \ ------------------------------\
41078 \ ------------------------------\
41079 #1000 20_US \ 1- wait 20 ms
41080 %011 TOP_LCD \ 2- send DB5=DB4=1
41081 #205 20_US \ 3- wait 4,1 ms
41082 %011 TOP_LCD \ 4- send again DB5=DB4=1
41083 #5 20_US \ 5- wait 0,1 ms
41084 %011 TOP_LCD \ 6- send again again DB5=DB4=1
41085 #2 20_US \ wait 40 us = LCD cycle
41086 %010 TOP_LCD \ 7- send DB5=1 DB4=0
41087 #2 20_US \ wait 40 us = LCD cycle
41088 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41089 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41090 LCD_CLEAR \ 10- "LCD_Clear"
41091 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41092 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41093 LCD_CLEAR \ 10- "LCD_Clear"
41094 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41095 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41096 CR ." I love you" \ display message on LCD
41097 ['] CR >BODY IS CR \ CR executes its default value
41098 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
41099 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
41102 \ ------------------------------\
41104 \ ------------------------------\
41105 CODE START \ this routine replaces WARM and COLD default values by these of this application.
41106 \ ------------------------------\
41107 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
41108 0= IF \ if not done, customizes MARKER_DOES
41109 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
41110 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
41111 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
41112 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
41113 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
41114 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
41115 MOV #RC5_INT,&IR_VEC \ init interrupt vector
41116 MOV #INI_R2L,PC \ then execute new INI_APP, without return
41120 \ ------------------------------\
41123 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
41125 MARKER {RC5TOLCD} \ restore the state before MARKER definition
41126 \ \ {UARTI2CS}+8 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
41127 6 ALLOT \ {UARTI2CS}+10: make room to save previous INI_APP address
41128 \ {RC5TOLCD}+12: make room to save previous WDT_TIM_0_VEC
41129 \ {RC5TOLCD}+14: make room to save previous IR_VEC
41131 [UNDEFINED] CONSTANT [IF]
41132 \ https://forth-standard.org/standard/core/CONSTANT
41133 \ CONSTANT <name> n -- define a Forth CONSTANT
41137 MOV TOS,-2(W) \ PFA = n
41144 [UNDEFINED] STATE [IF]
41145 \ https://forth-standard.org/standard/core/STATE
41146 \ STATE -- a-addr holds compiler state
41147 STATEADR CONSTANT STATE
41151 \ https://forth-standard.org/standard/core/Equal
41152 \ = x1 x2 -- flag test x1=x2
41159 XOR #-1,TOS \ 1 flag Z = 1
41164 [UNDEFINED] IF [IF] \ define IF and THEN
41165 \ https://forth-standard.org/standard/core/IF
41166 \ IF -- IFadr initialize conditional forward branch
41167 CODE IF \ immediate
41170 MOV &DP,TOS \ -- HERE
41171 ADD #4,&DP \ compile one word, reserve one word
41172 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
41173 ADD #2,TOS \ -- HERE+2=IFadr
41177 \ https://forth-standard.org/standard/core/THEN
41178 \ THEN IFadr -- resolve forward branch
41179 CODE THEN \ immediate
41180 MOV &DP,0(TOS) \ -- IFadr
41186 [UNDEFINED] ELSE [IF]
41187 \ https://forth-standard.org/standard/core/ELSE
41188 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
41189 CODE ELSE \ immediate
41190 ADD #4,&DP \ make room to compile two words
41191 MOV &DP,W \ W=HERE+4
41193 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
41195 MOV W,TOS \ -- ELSEadr
41200 [UNDEFINED] IS [IF] \ define DEFER! and IS
41202 \ https://forth-standard.org/standard/core/DEFERStore
41203 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
41204 CODE DEFER! \ xt2 xt1 --
41205 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
41210 \ https://forth-standard.org/standard/core/IS
41213 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
41214 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
41215 \ or in a definition : ... ['] U. IS DISPLAY ...
41216 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
41218 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
41222 IF POSTPONE ['] POSTPONE DEFER!
41228 [UNDEFINED] >BODY [IF]
41229 \ https://forth-standard.org/standard/core/toBODY
41230 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
41237 \ CODE 20uS \ n -- 8MHz version
41238 \ BEGIN \ 4 + 16 ~ loop
41239 \ MOV #39,rDOCON \ 39
41246 \ MOV #XDOCON,rDOCON \ 2
41251 CODE 20_US \ n -- n * 20 us
41252 BEGIN \ here we presume that LCD_TIM_IFG = 1...
41254 BIT #1,&LCD_TIM_CTL \ 3
41255 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
41256 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
41258 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
41263 CODE TOP_LCD \ LCD Sample
41264 \ \ if write : %xxxx_WWWW --
41265 \ \ if read : -- %0000_RRRR
41266 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41267 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41268 0= IF \ write LCD bits pattern
41269 AND.B #LCD_DB,TOS \
41270 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41271 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41274 THEN \ read LCD bits pattern
41277 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41278 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41279 AND.B #LCD_DB,TOS \
41283 CODE LCD_WRC \ char -- Write Char
41284 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41286 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
41287 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
41288 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41289 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41290 COLON \ high level word starts here
41291 TOP_LCD 2 20_US \ write high nibble first
41295 CODE LCD_WRF \ func -- Write Fonction
41296 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41300 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
41301 : LCD_HOME $02 LCD_WRF 100 20_us ;
41303 \ [UNDEFINED] OR [IF]
41305 \ \ https://forth-standard.org/standard/core/OR
41306 \ \ C OR x1 x2 -- x3 logical OR
41314 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
41315 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
41316 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
41317 \ : LCD_FN_SET $20 OR LCD_WrF ;
41318 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
41319 \ : LCD_GOTO $80 OR LCD_WrF ;
41322 \ CODE LCD_RDS \ -- status Read Status
41323 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41324 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41325 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41326 \ COLON \ starts a FORTH word
41327 \ TOP_LCD 2 20_us \ -- %0000_HHHH
41328 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
41329 \ HI2LO \ switch from FORTH to assembler
41330 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
41331 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
41332 \ MOV @RSP+,IP \ restore IP saved by COLON
41336 \ CODE LCD_RDC \ -- char Read Char
41337 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41342 \ ******************************\
41343 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41344 \ ******************************\
41345 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
41346 BIT.B #SW2,&SW2_IN \ test switch S2
41347 0= IF \ case of switch S2 pressed
41348 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
41350 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
41353 BIT.B #SW1,&SW1_IN \ test switch S1 input
41354 0= IF \ case of Switch S1 pressed
41355 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
41357 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
41364 \ ******************************\
41365 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
41366 \ ******************************\
41367 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41368 \ ******************************\
41369 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41370 \ \ SMclock = 8|16|24 MHz
41371 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
41372 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
41373 \ \ SR(9)=new Toggle bit memory (ADD on)
41374 \ ******************************\
41375 \ RC5_FirstStartBitHalfCycle: \
41376 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
41377 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
41378 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
41380 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
41381 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
41383 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
41384 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
41386 MOV #1778,X \ RC5_Period * 1us
41387 MOV #14,W \ count of loop
41389 \ ******************************\
41390 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
41391 \ ******************************\ |
41392 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
41393 \ RC5_Compute_3/4_Period: \ |
41394 RRUM #1,X \ X=1/2 cycle |
41397 ADD X,Y \ Y=3/4 cycle
41398 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
41400 \ ******************************\
41401 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
41402 \ ******************************\
41403 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41404 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
41405 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41406 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41407 SUB #1,W \ decrement count loop
41408 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
41409 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41410 0<> WHILE \ ----> out of loop ----+
41411 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
41413 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
41414 CMP Y,X \ 1 | cycle time out of bound ?
41415 U>= IF \ 2 ^ | yes:
41416 BIC #$30,&RC5_TIM_CTL \ | | stop timer
41417 GOTO FW1 \ | | quit on truncated RC5 message
41419 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
41421 REPEAT \ ----> loop back --+ | with X = new RC5_period value
41422 \ ******************************\ |
41423 \ RC5_SampleEndOf: \ <---------------------+
41424 \ ******************************\
41425 BIC #$30,&RC5_TIM_CTL \ stop timer
41426 \ ******************************\
41427 \ RC5_ComputeNewRC5word \
41428 \ ******************************\
41429 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
41430 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
41431 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
41432 \ ******************************\
41433 \ RC5_ComputeC6bit \
41434 \ ******************************\
41435 BIT #BIT14,T \ test /C6 bit in T
41436 0= IF BIS #BIT6,X \ set C6 bit in X
41437 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
41438 \ ******************************\
41439 \ RC5_CommandByteIsDone \ -- BASE RC5_code
41440 \ ******************************\
41441 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
41442 \ ******************************\
41443 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
41444 XOR @RSP,T \ (new XOR old) Toggle bits
41445 BIT #UF10,T \ repeated RC5_command ?
41446 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
41447 XOR #UF10,0(RSP) \ 5 toggle bit memory
41448 \ ******************************\
41449 \ Display IR_RC5 code \
41450 \ ******************************\
41451 SUB #8,PSP \ TOS -- x x x x TOS
41452 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
41453 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
41454 MOV #$10,&BASEADR \ set hexadecimal base
41455 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
41456 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
41457 LO2HI \ switch from assembler to FORTH
41458 LCD_CLEAR \ set LCD cursor at home
41459 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
41460 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
41461 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
41462 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
41463 HI2LO \ -- switch from FORTH to assembler
41464 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
41465 MOV @PSP+,TOS \ -- TOS
41467 MOV @RSP+,SR \ restore SR flags
41468 BIC #%1111_1000,SR \ but force CPU Active Mode
41469 RET \ (instead of RETI)
41473 \ ------------------------------\
41474 HDNCODE STOP_R2L \ define new STOP_APP
41475 \ ------------------------------\
41476 CMP #RET_ADR,&{RC5TOLCD}+8 \
41477 0<> IF \ if previous START executing
41478 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
41479 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
41480 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
41481 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
41482 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
41483 MOV #RET_ADR,&{RC5TOLCD}+8 \ clear MARKER_DOES call
41484 MOV &{RC5TOLCD}+10,&WARM+2 \ restore previous ini_APP
41485 MOV &{RC5TOLCD}+12,&WDT_TIM_0_VEC \ restore Vector previous value
41486 MOV &{RC5TOLCD}+14,&IR_VEC \ restore Vector previous value
41487 MOV &{RC5TOLCD}+10,PC \ run previous INI_APP, then RET
41492 \ ------------------------------\
41494 \ ------------------------------\
41495 BW1 \ <-- INI_R2L for some events
41497 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
41499 ." RC5toLCD is removed,"
41500 ." type START to restart"
41503 \ ------------------------------\
41505 \ ------------------------------\
41506 HDNCODE INI_R2L \ this routine completes the init of system, i.e. FORTH + this app.
41507 \ ------------------------------\
41509 \ ------------------------------\
41510 BIC #1,&PM5CTL0 \ activate I/O to enable SW2 test
41511 \ ------------------------------\
41512 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
41513 \ ------------------------------\
41514 MOV &RSTIV_MEM,TOS \ SYSRSTIV = $00|$02|$04|$0E|$xx = POWER_ON|RST|SVSH_threshold|SYS_failures
41515 CMP #$0E,TOS \ RSTIV_MEM = SVSHIFG SVSH event ?
41517 CMP #$0A,TOS \ RSTIV_MEM >= violation memory protected areas ?
41518 U>= ?GOTO BW1 \ execute STOP_R2L then RET to BODY of WARM
41520 BIT.B #SW2,&SW2_IN \ hardware SW2+RST ?
41521 0= ?GOTO BW1 \ hardware SW2+RST execute STOP_U2I then RET to BODY of WARM
41522 \ CMP #4,TOS \ hardware RST
41523 \ 0= ?GOTO BW1 \ hardware RST performs STOP.
41524 \ CMP #2,TOS \ Power_ON event
41525 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
41527 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
41529 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
41531 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
41532 MOV #0,&RSTIV_MEM \ clear RSTIV_MEM after use and before next RST event!
41533 \ ------------------------------\
41534 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
41535 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41536 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41537 \ -- \ID input divider \ 10 = /4
41538 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
41539 \ - \TBCLR TimerB Clear
41542 \ -------------------------------\
41543 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41544 \ -- \CM Capture Mode
41549 \ --- \OUTMOD \ 011 = set/reset
41555 \ -------------------------------\
41557 \ -------------------------------\
41559 \ ------------------------------\
41560 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
41561 \ ------------------------------\
41562 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
41563 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
41564 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
41565 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
41567 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
41568 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
41570 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
41571 \ ------------------------------\
41572 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
41573 \ ------------------------------\
41574 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
41575 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
41576 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41577 \ ------------------------------\
41578 BIS.B #LCDVo,&LCDVo_DIR \
41579 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
41580 \ ------------------------------\
41581 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41582 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41583 \ ------------------------------\
41584 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41585 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41586 \ ******************************\
41588 \ ******************************\
41589 BIS.B #RC5,&IR_IE \ enable RC5_Int
41590 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41591 \ ******************************\
41592 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
41593 \ ******************************\
41594 \ %01 0001 0100 \ TAxCTL
41595 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
41596 \ -- \ ID divided by 1
41597 \ -- \ MC MODE = up to TAxCCRn
41598 \ - \ TACLR clear timer count
41601 \ ------------------------------\
41602 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
41603 \ ------------------------------\
41605 \ --- \ TAIDEX pre divisor
41606 \ ------------------------------\
41607 \ %0000 0000 0000 0101 \ TAxCCR0
41608 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
41609 \ ------------------------------\
41610 \ %0000 0000 0001 0000 \ TAxCCTL0
41611 \ - \ CAP capture/compare mode = compare
41614 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
41615 \ ------------------------------\
41616 \ define LPM mode for ACCEPT \
41617 \ ------------------------------\
41618 \ MOV #LPM4+GIE,&LPM_MODE \ with MSP430FR59xx
41619 \ MOV #LPM2+GIE,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41620 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41621 \ ------------------------------\
41623 \ ------------------------------\
41625 \ ------------------------------\
41626 #1000 20_US \ 1- wait 20 ms
41627 %011 TOP_LCD \ 2- send DB5=DB4=1
41628 #205 20_US \ 3- wait 4,1 ms
41629 %011 TOP_LCD \ 4- send again DB5=DB4=1
41630 #5 20_US \ 5- wait 0,1 ms
41631 %011 TOP_LCD \ 6- send again again DB5=DB4=1
41632 #2 20_US \ wait 40 us = LCD cycle
41633 %010 TOP_LCD \ 7- send DB5=1 DB4=0
41634 #2 20_US \ wait 40 us = LCD cycle
41635 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41636 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41637 LCD_CLEAR \ 10- "LCD_Clear"
41638 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41639 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41640 LCD_CLEAR \ 10- "LCD_Clear"
41641 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41642 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41643 CR ." I love you" \ display message on LCD
41644 ['] CR >BODY IS CR \ CR executes its default value
41645 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
41646 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
41649 \ ------------------------------\
41651 \ ------------------------------\
41652 CODE START \ this routine replaces WARM and COLD default values by these of this application.
41653 \ ------------------------------\
41654 CMP #RET_ADR,&{RC5TOLCD}+8 \ init R2L once, only if MARKER_DOES is not initialized
41655 0= IF \ if not done, customizes MARKER_DOES
41656 MOV #STOP_R2L,&{RC5TOLCD}+8 \ execution of {RC5TOLCD} will perform STOP_R2L.
41657 MOV &WARM+2,&{RC5TOLCD}+10 \ save previous INI_APP subroutine
41658 MOV #INI_R2L,&WARM+2 \ replace it by RC5toLCD INI_APP
41659 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+12 \ save Vector previous value
41660 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
41661 MOV &IR_VEC,&{RC5TOLCD}+14 \ save Vector previous value
41662 MOV #RC5_INT,&IR_VEC \ init interrupt vector
41663 MOV #INI_R2L,PC \ then execute new INI_APP, without return
41667 \ ------------------------------\
41672 ; downloading PROG100k.4th is done
41673 RST_HERE ; this app is protected against <reset>