1 \ -*- coding: utf-8 -*-
3 ; -----------------------------------
5 ; -----------------------------------
7 ; load and compile 10kb (9 x RC52LCD)
9 \ to see kernel options, download FastForthSpecs.f
10 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, FREQUENCY = 8/16/24 MHz
12 \ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
13 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
17 \ from scite editor : copy your target selection in (shift+F8) parameter 1:
21 \ drag and drop this file onto SendSourceFileToTarget.bat
22 \ then select your TARGET when asked.
25 \ ================================================================================
26 \ REGISTERS USAGE for embedded MSP430 ASSEMBLER
27 \ ================================================================================
28 \ don't use R2, R3, R4
29 \ R5, R6, R7 must be PUSHed/POPed before/after use, OR restored after: MOV #{XDOCOL|XDOCON|R>},{rDODOES|rDOCON|rDOVAR}
30 \ scratch registers Y to S are free,
31 \ under interrupt, IP is free,
32 \ use FORTH rules for reg. TOS, PSP, RSP.
34 \ PUSHM order : PSP,TOS, IP, S , T , W , X , Y ,rDOVAR,rDOCON,rDODOES,rDOCOL, R3, SR,RSP, PC
35 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
37 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
39 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
40 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
42 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
44 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
45 \ ASSEMBLER conditionnal usage before ?GOTO : S< S>= U< U>= 0= 0<> 0<
48 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
49 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
50 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
52 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
53 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
54 \ without usage of an auxiliary 5V to feed the LCD_Vo
55 \ and without potentiometer to adjust the LCD contrast :
56 \ to adjust LCD contrast, just press S1 (-) or S2 (+)
57 \ LCDVo current consumption ~ 500 uA.
59 \ ===================================================================================
60 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
61 \ ===================================================================================
64 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
66 \ GND <-------o---0V0----------> 1 LCD_Vss
67 \ VCC >-------|---3V6-----o----> 2 LCD_Vdd
74 \ TB0.2 >---||--o--^/\/\/v--o----> 3 LCD_Vo (= 0V6 without modulation)
75 \ -------------------------> 4 LCD_RW
76 \ -------------------------> 5 LCD_RW
77 \ -------------------------> 6 LCD_EN
78 \ <------------------------> 11 LCD_DB4
79 \ <------------------------> 12 LCD_DB5
80 \ <------------------------> 13 LCD_DB5
81 \ <------------------------> 14 LCD_DB7
83 \ <----- LCD contrast + <--- Sw1 <--- (finger) :-)
84 \ <----- LCD contrast - <--- Sw2 <--- (finger) :-)
86 \ rc5 <--- OUT IR_Receiver (1 TSOP32236)
89 \ first, we test for downloading driver only if UART TERMINAL target
94 SUB #309,TOS \ FastForth V3.9
96 'CR' EMIT \ return to column 1 without 'LF'
97 ABORT" FastForth V3.9 please!"
98 RST_RET \ remove ABORT_UARTI2CS definition before resuming
103 MARKER {RC5TOLCD} \ restore the state before MARKER definition
104 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
105 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
106 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
107 \ {RC5TOLCD}+4 make room to save previous IR_VEC
108 \ {RC5TOLCD}+6 make room for 20 us count loop.
112 CODE TSTBIT \ addr bit_mask -- true/flase flag
119 \ https://forth-standard.org/standard/core/Equal
120 \ = x1 x2 -- flag test x1=x2
129 XOR #-1,TOS \ 1 flag Z = 1
135 [IF] \ define IF and THEN
136 \ https://forth-standard.org/standard/core/IF
137 \ IF -- IFadr initialize conditional forward branch
141 MOV &DP,TOS \ -- HERE
142 ADD #4,&DP \ compile one word, reserve one word
143 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
144 ADD #2,TOS \ -- HERE+2=IFadr
148 \ https://forth-standard.org/standard/core/THEN
149 \ THEN IFadr -- resolve forward branch
150 CODE THEN \ immediate
151 MOV &DP,0(TOS) \ -- IFadr
157 \ https://forth-standard.org/standard/core/ELSE
158 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
161 CODE ELSE \ immediate
162 ADD #4,&DP \ make room to compile two words
165 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
167 MOV W,TOS \ -- ELSEadr
172 \ \ https://forth-standard.org/standard/core/DEFERStore
173 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
175 \ [IF] \ define DEFER! and IS
176 \ CODE DEFER! \ xt2 xt1 --
177 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
182 \ \ https://forth-standard.org/standard/core/IS
185 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
186 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
187 \ \ or in a definition : ... ['] U. IS DISPLAY ...
188 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
190 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
194 \ IF POSTPONE ['] POSTPONE DEFER!
200 \ https://forth-standard.org/standard/core/CR
201 \ CR -- send CR+LF to the output device
204 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
205 CODE CR \ part I : DEFERed definition of CR
206 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
214 \ https://forth-standard.org/standard/core/toBODY
215 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
225 BEGIN \ J_loop 8000 16000 24000 kHz
226 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
227 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
239 \ \ if write : %xxxx_WWWW --
240 \ \ if read : -- %0000_RRRR
241 CODE TOP_LCD \ LCD Sample
242 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
243 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
244 0= IF \ write LCD bits pattern
246 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
247 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
250 THEN \ read LCD bits pattern
253 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
254 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
259 CODE LCD_WRC \ char -- Write Char
260 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
262 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
263 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
264 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
265 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
266 COLON \ high level word starts here
267 TOP_LCD 2 20_US \ write high nibble first
271 CODE LCD_WRF \ func -- Write Fonction
272 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
276 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
277 : LCD_HOME $02 LCD_WRF 100 20_us ;
310 \ CODE LCD_RDS \ -- status Read Status
311 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
312 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
313 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
314 \ COLON \ starts a FORTH word
315 \ TOP_LCD 2 20_us \ -- %0000_HHHH
316 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
317 \ HI2LO \ switch from FORTH to assembler
318 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
319 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
320 \ MOV @RSP+,IP \ restore IP saved by COLON
324 \ CODE LCD_RDC \ -- char Read Char
325 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
330 \ ********************************\
331 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
332 \ ********************************\
333 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
334 BIT.B #SW2,&SW2_IN \ test switch S2
335 0= IF \ case of switch S2 pressed
336 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
338 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
341 BIT.B #SW1,&SW1_IN \ test switch S1 input
342 0= IF \ case of Switch S1 pressed
343 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
345 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
351 \ ********************************\
353 \ ********************************\
354 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
355 \ ********************************\
356 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
357 \ ********************************\
358 \ \ in : SR(9)=old Toggle bit memory (ADD on)
359 \ \ SMclock = 8|16|24 MHz
360 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
361 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
362 \ \ SR(9)=new Toggle bit memory (ADD on)
363 \ ********************************\
364 \ RC5_FirstStartBitHalfCycle: \
365 \ ********************************\
366 MOV #1778,X \ RC5_Period in us
367 MOV #14,W \ count of loop
369 \ ****************************\
370 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
371 \ ****************************\ |
372 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
373 \ RC5_Compute_3/4_Period: \ |
374 RRUM #1,X \ X=1/2 cycle |
377 ADD X,Y \ Y=3/4 cycle
379 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
381 \ ****************************\
382 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
383 \ ****************************\
384 BIT.B #RC5,&IR_IN \ C_flag = IR bit
385 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
386 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
387 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
388 SUB #1,W \ decrement count loop
389 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
390 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
391 0<> WHILE \ ----> out of loop ----+
392 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
394 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
395 CMP Y,X \ 1 ^ | cycle time out of bound ?
396 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
397 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
399 REPEAT \ ----> loop back --+ | with X = new RC5_period value
400 \ ********************************\ |
401 \ RC5_SampleEndOf: \ <---------------------+
402 \ ********************************\
403 BIC #$30,&RC5_TIM_CTL \ stop timer
404 \ ********************************\
405 \ RC5_ComputeNewRC5word \
406 \ ********************************\
407 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
408 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
409 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
410 \ ********************************\
412 \ ********************************\
413 BIT #BIT14,T \ test /C6 bit in T
414 0= IF BIS #BIT6,X \ set C6 bit in X
415 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
416 \ ********************************\
417 \ RC5_CommandByteIsDone \
418 \ ********************************\
419 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
420 \ ********************************\
421 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
422 XOR @RSP,T \ (new XOR old) Toggle bits
423 BIT #UF10,T \ repeated RC5_command ?
424 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
425 XOR #UF10,0(RSP) \ 5 toggle bit memory
426 \ ********************************\
427 \ Display IR_RC5 code \
428 \ ********************************\
429 SUB #6,PSP \ -- x x x TOS
430 MOV TOS,4(PSP) \ -- TOS x x TOS
431 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
432 MOV #$10,&BASEADR \ set hexadecimal base
433 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
434 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
435 LO2HI \ switch from assembler to FORTH
436 LCD_CLEAR \ set LCD cursor at home
437 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
438 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
439 TYPE \ -- TOS Base display "$xx" on LCD
440 ['] EMIT >BODY IS EMIT \ restore EMIT
441 HI2LO \ switch from FORTH to assembler
442 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
444 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
445 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
448 \ ********************************\
450 \ define our STOP_APP
451 \ ----------------------------------\
452 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
453 \ ----------------------------------\
454 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
455 0= IF \ only if START is done
456 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
457 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
458 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
459 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
460 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
462 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
463 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
465 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
467 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
469 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
470 MOV @W+,&IR_VEC \ restore Vector previous value
472 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
474 \ ----------------------------------\
476 \ ----------------------------------\
477 CODE STOP \ also called by INIT_R2L for some events
478 \ ----------------------------------\
482 ." type START to start RC5toLCD"
484 \ ----------------------------------\
486 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
487 \ ----------------------------------\
488 HDNCODE INIT_R2L \ called by START|SYS
489 \ ----------------------------------\
490 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
491 \ - - \CNTL Counter lentgh \ 00 = 16 bits
492 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
493 \ -- \ID input divider \ 10 = /4
494 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
495 \ - \TBCLR TimerB Clear
498 \ ----------------------------------\
499 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
500 \ -- \CM Capture Mode
505 \ --- \OUTMOD \ 011 = set/reset
511 \ ----------------------------------\
513 \ ----------------------------------\
515 \ ----------------------------------\
516 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
517 \ ----------------------------------\
518 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
519 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
520 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
523 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
524 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
528 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
529 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
531 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
532 \ ----------------------------------\
533 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
534 \ ----------------------------------\
535 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
536 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
537 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
538 \ ----------------------------------\
539 BIS.B #LCDVo,&LCDVo_DIR \
540 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
541 \ ----------------------------------\
542 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
543 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
544 \ ----------------------------------\
545 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
546 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
547 \ ----------------------------------\
549 \ ----------------------------------\
550 BIS.B #RC5,&IR_IE \ enable RC5_Int
551 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
552 \ ----------------------------------\
553 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
554 \ ----------------------------------\
555 \ %01 0001 0100 \ TAxCTL
556 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
557 \ -- \ ID divided by 1
558 \ -- \ MC MODE = up to TAxCCRn
559 \ - \ TACLR clear timer count
562 \ ----------------------------------\
563 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
564 \ ----------------------------------\
566 \ --- \ TAIDEX pre divisor
567 \ ----------------------------------\
568 \ %0000 0000 0000 0101 \ TAxCCR0
569 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
570 \ ----------------------------------\
571 \ %0000 0000 0001 0000 \ TAxCCTL0
572 \ - \ CAP capture/compare mode = compare
575 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
576 \ ----------------------------------\
578 \ ----------------------------------\
579 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
580 \ ----------------------------------\
581 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
582 \ ----------------------------------\
583 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
585 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
586 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
588 \ CMP #2,TOS \ Power_ON event
589 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
590 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
591 0= ?GOTO BW1 \ if yes run STOP.
592 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
593 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
594 \ ----------------------------------\
596 \ ----------------------------------\
598 \ ----------------------------------\
599 #1000 20_US \ 1- wait 20 ms
600 %011 TOP_LCD \ 2- send DB5=DB4=1
601 #205 20_US \ 3- wait 4,1 ms
602 %011 TOP_LCD \ 4- send again DB5=DB4=1
603 #5 20_US \ 5- wait 0,1 ms
604 %011 TOP_LCD \ 6- send again again DB5=DB4=1
605 #2 20_US \ wait 40 us = LCD cycle
606 %010 TOP_LCD \ 7- send DB5=1 DB4=0
607 #2 20_US \ wait 40 us = LCD cycle
608 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
609 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
610 LCD_CLEAR \ 10- "LCD_Clear"
611 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
612 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
613 LCD_CLEAR \ 10- "LCD_Clear"
615 MOV @RSP+,PC \ RET to WARM|START
617 \ ----------------------------------\
619 \ ----------------------------------\
620 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
621 \ ----------------------------------\
622 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
624 MOV @IP+,PC \ does nothing if already initialised
626 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
627 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
629 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
630 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
632 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
633 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
635 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
636 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
637 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
638 MOV #RC5_INT,&IR_VEC \ init interrupt vector
639 \ ----------------------------------\
640 \ init 20 us count loop \ see 20_US
641 \ ----------------------------------\ -- TOS
642 SUB #6,PSP \ -- x x x TOS
643 MOV TOS,4(PSP) \ -- TOS x x TOS
644 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
645 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
646 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
647 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
648 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
649 ADD #4,PSP \ -- TOS QUOThi
650 MOV @PSP+,TOS \ -- TOS
651 \ ----------------------------------\
652 CALL #INIT_R2L \ run new INIT_HARD_APP
654 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
655 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
656 \ CR ." I love you" \ display message on LCD
657 \ ['] CR >BODY IS CR \ CR executes its default value
658 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
659 ." RC5toLCD is running," \
660 ." Type STOP to quit." \ display message on FastForth Terminal
662 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
664 \ ----------------------------------\
670 MARKER {RC5TOLCD} \ restore the state before MARKER definition
671 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
672 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
673 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
674 \ {RC5TOLCD}+4 make room to save previous IR_VEC
675 \ {RC5TOLCD}+6 make room for 20 us count loop.
679 CODE TSTBIT \ addr bit_mask -- true/flase flag
686 \ https://forth-standard.org/standard/core/Equal
687 \ = x1 x2 -- flag test x1=x2
696 XOR #-1,TOS \ 1 flag Z = 1
702 [IF] \ define IF and THEN
703 \ https://forth-standard.org/standard/core/IF
704 \ IF -- IFadr initialize conditional forward branch
708 MOV &DP,TOS \ -- HERE
709 ADD #4,&DP \ compile one word, reserve one word
710 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
711 ADD #2,TOS \ -- HERE+2=IFadr
715 \ https://forth-standard.org/standard/core/THEN
716 \ THEN IFadr -- resolve forward branch
717 CODE THEN \ immediate
718 MOV &DP,0(TOS) \ -- IFadr
724 \ https://forth-standard.org/standard/core/ELSE
725 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
728 CODE ELSE \ immediate
729 ADD #4,&DP \ make room to compile two words
732 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
734 MOV W,TOS \ -- ELSEadr
739 \ \ https://forth-standard.org/standard/core/DEFERStore
740 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
742 \ [IF] \ define DEFER! and IS
743 \ CODE DEFER! \ xt2 xt1 --
744 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
749 \ \ https://forth-standard.org/standard/core/IS
752 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
753 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
754 \ \ or in a definition : ... ['] U. IS DISPLAY ...
755 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
757 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
761 \ IF POSTPONE ['] POSTPONE DEFER!
767 \ https://forth-standard.org/standard/core/CR
768 \ CR -- send CR+LF to the output device
771 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
772 CODE CR \ part I : DEFERed definition of CR
773 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
781 \ https://forth-standard.org/standard/core/toBODY
782 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
792 BEGIN \ J_loop 8000 16000 24000 kHz
793 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
794 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
806 \ \ if write : %xxxx_WWWW --
807 \ \ if read : -- %0000_RRRR
808 CODE TOP_LCD \ LCD Sample
809 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
810 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
811 0= IF \ write LCD bits pattern
813 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
814 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
817 THEN \ read LCD bits pattern
820 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
821 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
826 CODE LCD_WRC \ char -- Write Char
827 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
829 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
830 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
831 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
832 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
833 COLON \ high level word starts here
834 TOP_LCD 2 20_US \ write high nibble first
838 CODE LCD_WRF \ func -- Write Fonction
839 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
843 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
844 : LCD_HOME $02 LCD_WRF 100 20_us ;
877 \ CODE LCD_RDS \ -- status Read Status
878 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
879 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
880 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
881 \ COLON \ starts a FORTH word
882 \ TOP_LCD 2 20_us \ -- %0000_HHHH
883 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
884 \ HI2LO \ switch from FORTH to assembler
885 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
886 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
887 \ MOV @RSP+,IP \ restore IP saved by COLON
891 \ CODE LCD_RDC \ -- char Read Char
892 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
897 \ ********************************\
898 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
899 \ ********************************\
900 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
901 BIT.B #SW2,&SW2_IN \ test switch S2
902 0= IF \ case of switch S2 pressed
903 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
905 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
908 BIT.B #SW1,&SW1_IN \ test switch S1 input
909 0= IF \ case of Switch S1 pressed
910 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
912 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
918 \ ********************************\
920 \ ********************************\
921 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
922 \ ********************************\
923 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
924 \ ********************************\
925 \ \ in : SR(9)=old Toggle bit memory (ADD on)
926 \ \ SMclock = 8|16|24 MHz
927 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
928 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
929 \ \ SR(9)=new Toggle bit memory (ADD on)
930 \ ********************************\
931 \ RC5_FirstStartBitHalfCycle: \
932 \ ********************************\
933 MOV #1778,X \ RC5_Period in us
934 MOV #14,W \ count of loop
936 \ ****************************\
937 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
938 \ ****************************\ |
939 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
940 \ RC5_Compute_3/4_Period: \ |
941 RRUM #1,X \ X=1/2 cycle |
944 ADD X,Y \ Y=3/4 cycle
946 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
948 \ ****************************\
949 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
950 \ ****************************\
951 BIT.B #RC5,&IR_IN \ C_flag = IR bit
952 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
953 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
954 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
955 SUB #1,W \ decrement count loop
956 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
957 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
958 0<> WHILE \ ----> out of loop ----+
959 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
961 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
962 CMP Y,X \ 1 ^ | cycle time out of bound ?
963 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
964 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
966 REPEAT \ ----> loop back --+ | with X = new RC5_period value
967 \ ********************************\ |
968 \ RC5_SampleEndOf: \ <---------------------+
969 \ ********************************\
970 BIC #$30,&RC5_TIM_CTL \ stop timer
971 \ ********************************\
972 \ RC5_ComputeNewRC5word \
973 \ ********************************\
974 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
975 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
976 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
977 \ ********************************\
979 \ ********************************\
980 BIT #BIT14,T \ test /C6 bit in T
981 0= IF BIS #BIT6,X \ set C6 bit in X
982 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
983 \ ********************************\
984 \ RC5_CommandByteIsDone \
985 \ ********************************\
986 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
987 \ ********************************\
988 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
989 XOR @RSP,T \ (new XOR old) Toggle bits
990 BIT #UF10,T \ repeated RC5_command ?
991 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
992 XOR #UF10,0(RSP) \ 5 toggle bit memory
993 \ ********************************\
994 \ Display IR_RC5 code \
995 \ ********************************\
996 SUB #6,PSP \ -- x x x TOS
997 MOV TOS,4(PSP) \ -- TOS x x TOS
998 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
999 MOV #$10,&BASEADR \ set hexadecimal base
1000 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
1001 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
1002 LO2HI \ switch from assembler to FORTH
1003 LCD_CLEAR \ set LCD cursor at home
1004 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
1005 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1006 TYPE \ -- TOS Base display "$xx" on LCD
1007 ['] EMIT >BODY IS EMIT \ restore EMIT
1008 HI2LO \ switch from FORTH to assembler
1009 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
1011 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
1012 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
1015 \ ********************************\
1017 \ define our STOP_APP
1018 \ ----------------------------------\
1019 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
1020 \ ----------------------------------\
1021 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
1022 0= IF \ only if START is done
1023 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
1024 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
1025 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
1026 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
1027 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
1029 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
1030 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1032 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
1034 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
1036 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
1037 MOV @W+,&IR_VEC \ restore Vector previous value
1039 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
1041 \ ----------------------------------\
1043 \ ----------------------------------\
1044 CODE STOP \ also called by INIT_R2L for some events
1045 \ ----------------------------------\
1049 ." type START to start RC5toLCD"
1051 \ ----------------------------------\
1053 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
1054 \ ----------------------------------\
1055 HDNCODE INIT_R2L \ called by START|SYS
1056 \ ----------------------------------\
1057 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1058 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1059 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1060 \ -- \ID input divider \ 10 = /4
1061 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1062 \ - \TBCLR TimerB Clear
1065 \ ----------------------------------\
1066 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1067 \ -- \CM Capture Mode
1072 \ --- \OUTMOD \ 011 = set/reset
1078 \ ----------------------------------\
1080 \ ----------------------------------\
1082 \ ----------------------------------\
1083 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1084 \ ----------------------------------\
1085 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
1086 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1087 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1090 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1091 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1095 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1096 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1098 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1099 \ ----------------------------------\
1100 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1101 \ ----------------------------------\
1102 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1103 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1104 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1105 \ ----------------------------------\
1106 BIS.B #LCDVo,&LCDVo_DIR \
1107 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1108 \ ----------------------------------\
1109 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1110 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1111 \ ----------------------------------\
1112 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1113 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1114 \ ----------------------------------\
1116 \ ----------------------------------\
1117 BIS.B #RC5,&IR_IE \ enable RC5_Int
1118 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1119 \ ----------------------------------\
1120 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1121 \ ----------------------------------\
1122 \ %01 0001 0100 \ TAxCTL
1123 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1124 \ -- \ ID divided by 1
1125 \ -- \ MC MODE = up to TAxCCRn
1126 \ - \ TACLR clear timer count
1129 \ ----------------------------------\
1130 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1131 \ ----------------------------------\
1133 \ --- \ TAIDEX pre divisor
1134 \ ----------------------------------\
1135 \ %0000 0000 0000 0101 \ TAxCCR0
1136 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1137 \ ----------------------------------\
1138 \ %0000 0000 0001 0000 \ TAxCCTL0
1139 \ - \ CAP capture/compare mode = compare
1142 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1143 \ ----------------------------------\
1145 \ ----------------------------------\
1146 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
1147 \ ----------------------------------\
1148 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
1149 \ ----------------------------------\
1150 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
1152 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
1153 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
1155 \ CMP #2,TOS \ Power_ON event
1156 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1157 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
1158 0= ?GOTO BW1 \ if yes run STOP.
1159 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
1160 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
1161 \ ----------------------------------\
1163 \ ----------------------------------\
1165 \ ----------------------------------\
1166 #1000 20_US \ 1- wait 20 ms
1167 %011 TOP_LCD \ 2- send DB5=DB4=1
1168 #205 20_US \ 3- wait 4,1 ms
1169 %011 TOP_LCD \ 4- send again DB5=DB4=1
1170 #5 20_US \ 5- wait 0,1 ms
1171 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1172 #2 20_US \ wait 40 us = LCD cycle
1173 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1174 #2 20_US \ wait 40 us = LCD cycle
1175 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1176 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1177 LCD_CLEAR \ 10- "LCD_Clear"
1178 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1179 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1180 LCD_CLEAR \ 10- "LCD_Clear"
1182 MOV @RSP+,PC \ RET to WARM|START
1184 \ ----------------------------------\
1186 \ ----------------------------------\
1187 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
1188 \ ----------------------------------\
1189 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
1191 MOV @IP+,PC \ does nothing if already initialised
1193 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
1194 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1196 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
1197 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
1199 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
1200 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
1202 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
1203 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1204 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
1205 MOV #RC5_INT,&IR_VEC \ init interrupt vector
1206 \ ----------------------------------\
1207 \ init 20 us count loop \ see 20_US
1208 \ ----------------------------------\ -- TOS
1209 SUB #6,PSP \ -- x x x TOS
1210 MOV TOS,4(PSP) \ -- TOS x x TOS
1211 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
1212 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
1213 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
1214 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
1215 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
1216 ADD #4,PSP \ -- TOS QUOThi
1217 MOV @PSP+,TOS \ -- TOS
1218 \ ----------------------------------\
1219 CALL #INIT_R2L \ run new INIT_HARD_APP
1221 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1222 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1223 \ CR ." I love you" \ display message on LCD
1224 \ ['] CR >BODY IS CR \ CR executes its default value
1225 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1226 ." RC5toLCD is running," \
1227 ." Type STOP to quit." \ display message on FastForth Terminal
1229 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
1231 \ ----------------------------------\
1235 MARKER {RC5TOLCD} \ restore the state before MARKER definition
1236 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
1237 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
1238 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
1239 \ {RC5TOLCD}+4 make room to save previous IR_VEC
1240 \ {RC5TOLCD}+6 make room for 20 us count loop.
1244 CODE TSTBIT \ addr bit_mask -- true/flase flag
1251 \ https://forth-standard.org/standard/core/Equal
1252 \ = x1 x2 -- flag test x1=x2
1261 XOR #-1,TOS \ 1 flag Z = 1
1267 [IF] \ define IF and THEN
1268 \ https://forth-standard.org/standard/core/IF
1269 \ IF -- IFadr initialize conditional forward branch
1273 MOV &DP,TOS \ -- HERE
1274 ADD #4,&DP \ compile one word, reserve one word
1275 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
1276 ADD #2,TOS \ -- HERE+2=IFadr
1280 \ https://forth-standard.org/standard/core/THEN
1281 \ THEN IFadr -- resolve forward branch
1282 CODE THEN \ immediate
1283 MOV &DP,0(TOS) \ -- IFadr
1289 \ https://forth-standard.org/standard/core/ELSE
1290 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
1293 CODE ELSE \ immediate
1294 ADD #4,&DP \ make room to compile two words
1295 MOV &DP,W \ W=HERE+4
1297 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
1299 MOV W,TOS \ -- ELSEadr
1304 \ \ https://forth-standard.org/standard/core/DEFERStore
1305 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1307 \ [IF] \ define DEFER! and IS
1308 \ CODE DEFER! \ xt2 xt1 --
1309 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
1310 \ MOV @PSP+,TOS \ --
1314 \ \ https://forth-standard.org/standard/core/IS
1317 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
1318 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
1319 \ \ or in a definition : ... ['] U. IS DISPLAY ...
1320 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1322 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1326 \ IF POSTPONE ['] POSTPONE DEFER!
1332 \ https://forth-standard.org/standard/core/CR
1333 \ CR -- send CR+LF to the output device
1336 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
1337 CODE CR \ part I : DEFERed definition of CR
1338 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
1346 \ https://forth-standard.org/standard/core/toBODY
1347 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1357 BEGIN \ J_loop 8000 16000 24000 kHz
1358 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
1359 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
1371 \ \ if write : %xxxx_WWWW --
1372 \ \ if read : -- %0000_RRRR
1373 CODE TOP_LCD \ LCD Sample
1374 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1375 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1376 0= IF \ write LCD bits pattern
1378 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1379 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1382 THEN \ read LCD bits pattern
1385 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1386 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1391 CODE LCD_WRC \ char -- Write Char
1392 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1394 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
1395 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
1396 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1397 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1398 COLON \ high level word starts here
1399 TOP_LCD 2 20_US \ write high nibble first
1403 CODE LCD_WRF \ func -- Write Fonction
1404 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1408 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1409 : LCD_HOME $02 LCD_WRF 100 20_us ;
1411 \ CODE LCD_ENTRY_SET
1422 \ CODE LCD_DSP_SHIFT
1432 \ CODE LCD_CGRAM_SET
1442 \ CODE LCD_RDS \ -- status Read Status
1443 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1444 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1445 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1446 \ COLON \ starts a FORTH word
1447 \ TOP_LCD 2 20_us \ -- %0000_HHHH
1448 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
1449 \ HI2LO \ switch from FORTH to assembler
1450 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
1451 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
1452 \ MOV @RSP+,IP \ restore IP saved by COLON
1456 \ CODE LCD_RDC \ -- char Read Char
1457 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1462 \ ********************************\
1463 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1464 \ ********************************\
1465 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1466 BIT.B #SW2,&SW2_IN \ test switch S2
1467 0= IF \ case of switch S2 pressed
1468 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1470 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1473 BIT.B #SW1,&SW1_IN \ test switch S1 input
1474 0= IF \ case of Switch S1 pressed
1475 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1477 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1483 \ ********************************\
1485 \ ********************************\
1486 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
1487 \ ********************************\
1488 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1489 \ ********************************\
1490 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1491 \ \ SMclock = 8|16|24 MHz
1492 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1493 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1494 \ \ SR(9)=new Toggle bit memory (ADD on)
1495 \ ********************************\
1496 \ RC5_FirstStartBitHalfCycle: \
1497 \ ********************************\
1498 MOV #1778,X \ RC5_Period in us
1499 MOV #14,W \ count of loop
1501 \ ****************************\
1502 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1503 \ ****************************\ |
1504 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1505 \ RC5_Compute_3/4_Period: \ |
1506 RRUM #1,X \ X=1/2 cycle |
1509 ADD X,Y \ Y=3/4 cycle
1511 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1513 \ ****************************\
1514 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1515 \ ****************************\
1516 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1517 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1518 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1519 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1520 SUB #1,W \ decrement count loop
1521 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1522 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1523 0<> WHILE \ ----> out of loop ----+
1524 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1526 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1527 CMP Y,X \ 1 ^ | cycle time out of bound ?
1528 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
1529 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1531 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1532 \ ********************************\ |
1533 \ RC5_SampleEndOf: \ <---------------------+
1534 \ ********************************\
1535 BIC #$30,&RC5_TIM_CTL \ stop timer
1536 \ ********************************\
1537 \ RC5_ComputeNewRC5word \
1538 \ ********************************\
1539 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1540 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1541 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1542 \ ********************************\
1543 \ RC5_ComputeC6bit \
1544 \ ********************************\
1545 BIT #BIT14,T \ test /C6 bit in T
1546 0= IF BIS #BIT6,X \ set C6 bit in X
1547 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1548 \ ********************************\
1549 \ RC5_CommandByteIsDone \
1550 \ ********************************\
1551 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
1552 \ ********************************\
1553 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1554 XOR @RSP,T \ (new XOR old) Toggle bits
1555 BIT #UF10,T \ repeated RC5_command ?
1556 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
1557 XOR #UF10,0(RSP) \ 5 toggle bit memory
1558 \ ********************************\
1559 \ Display IR_RC5 code \
1560 \ ********************************\
1561 SUB #6,PSP \ -- x x x TOS
1562 MOV TOS,4(PSP) \ -- TOS x x TOS
1563 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
1564 MOV #$10,&BASEADR \ set hexadecimal base
1565 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
1566 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
1567 LO2HI \ switch from assembler to FORTH
1568 LCD_CLEAR \ set LCD cursor at home
1569 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
1570 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1571 TYPE \ -- TOS Base display "$xx" on LCD
1572 ['] EMIT >BODY IS EMIT \ restore EMIT
1573 HI2LO \ switch from FORTH to assembler
1574 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
1576 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
1577 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
1580 \ ********************************\
1582 \ define our STOP_APP
1583 \ ----------------------------------\
1584 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
1585 \ ----------------------------------\
1586 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
1587 0= IF \ only if START is done
1588 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
1589 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
1590 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
1591 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
1592 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
1594 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
1595 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1597 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
1599 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
1601 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
1602 MOV @W+,&IR_VEC \ restore Vector previous value
1604 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
1606 \ ----------------------------------\
1608 \ ----------------------------------\
1609 CODE STOP \ also called by INIT_R2L for some events
1610 \ ----------------------------------\
1614 ." type START to start RC5toLCD"
1616 \ ----------------------------------\
1618 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
1619 \ ----------------------------------\
1620 HDNCODE INIT_R2L \ called by START|SYS
1621 \ ----------------------------------\
1622 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1623 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1624 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1625 \ -- \ID input divider \ 10 = /4
1626 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1627 \ - \TBCLR TimerB Clear
1630 \ ----------------------------------\
1631 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1632 \ -- \CM Capture Mode
1637 \ --- \OUTMOD \ 011 = set/reset
1643 \ ----------------------------------\
1645 \ ----------------------------------\
1647 \ ----------------------------------\
1648 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1649 \ ----------------------------------\
1650 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
1651 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1652 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1655 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1656 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1660 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1661 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1663 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1664 \ ----------------------------------\
1665 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1666 \ ----------------------------------\
1667 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1668 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1669 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1670 \ ----------------------------------\
1671 BIS.B #LCDVo,&LCDVo_DIR \
1672 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1673 \ ----------------------------------\
1674 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1675 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1676 \ ----------------------------------\
1677 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1678 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1679 \ ----------------------------------\
1681 \ ----------------------------------\
1682 BIS.B #RC5,&IR_IE \ enable RC5_Int
1683 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1684 \ ----------------------------------\
1685 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1686 \ ----------------------------------\
1687 \ %01 0001 0100 \ TAxCTL
1688 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1689 \ -- \ ID divided by 1
1690 \ -- \ MC MODE = up to TAxCCRn
1691 \ - \ TACLR clear timer count
1694 \ ----------------------------------\
1695 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1696 \ ----------------------------------\
1698 \ --- \ TAIDEX pre divisor
1699 \ ----------------------------------\
1700 \ %0000 0000 0000 0101 \ TAxCCR0
1701 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1702 \ ----------------------------------\
1703 \ %0000 0000 0001 0000 \ TAxCCTL0
1704 \ - \ CAP capture/compare mode = compare
1707 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1708 \ ----------------------------------\
1710 \ ----------------------------------\
1711 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
1712 \ ----------------------------------\
1713 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
1714 \ ----------------------------------\
1715 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
1717 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
1718 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
1720 \ CMP #2,TOS \ Power_ON event
1721 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1722 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
1723 0= ?GOTO BW1 \ if yes run STOP.
1724 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
1725 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
1726 \ ----------------------------------\
1728 \ ----------------------------------\
1730 \ ----------------------------------\
1731 #1000 20_US \ 1- wait 20 ms
1732 %011 TOP_LCD \ 2- send DB5=DB4=1
1733 #205 20_US \ 3- wait 4,1 ms
1734 %011 TOP_LCD \ 4- send again DB5=DB4=1
1735 #5 20_US \ 5- wait 0,1 ms
1736 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1737 #2 20_US \ wait 40 us = LCD cycle
1738 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1739 #2 20_US \ wait 40 us = LCD cycle
1740 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1741 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1742 LCD_CLEAR \ 10- "LCD_Clear"
1743 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1744 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1745 LCD_CLEAR \ 10- "LCD_Clear"
1747 MOV @RSP+,PC \ RET to WARM|START
1749 \ ----------------------------------\
1751 \ ----------------------------------\
1752 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
1753 \ ----------------------------------\
1754 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
1756 MOV @IP+,PC \ does nothing if already initialised
1758 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
1759 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1761 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
1762 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
1764 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
1765 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
1767 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
1768 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1769 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
1770 MOV #RC5_INT,&IR_VEC \ init interrupt vector
1771 \ ----------------------------------\
1772 \ init 20 us count loop \ see 20_US
1773 \ ----------------------------------\ -- TOS
1774 SUB #6,PSP \ -- x x x TOS
1775 MOV TOS,4(PSP) \ -- TOS x x TOS
1776 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
1777 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
1778 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
1779 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
1780 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
1781 ADD #4,PSP \ -- TOS QUOThi
1782 MOV @PSP+,TOS \ -- TOS
1783 \ ----------------------------------\
1784 CALL #INIT_R2L \ run new INIT_HARD_APP
1786 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1787 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1788 \ CR ." I love you" \ display message on LCD
1789 \ ['] CR >BODY IS CR \ CR executes its default value
1790 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1791 ." RC5toLCD is running," \
1792 ." Type STOP to quit." \ display message on FastForth Terminal
1794 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
1796 \ ----------------------------------\
1800 MARKER {RC5TOLCD} \ restore the state before MARKER definition
1801 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
1802 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
1803 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
1804 \ {RC5TOLCD}+4 make room to save previous IR_VEC
1805 \ {RC5TOLCD}+6 make room for 20 us count loop.
1809 CODE TSTBIT \ addr bit_mask -- true/flase flag
1816 \ https://forth-standard.org/standard/core/Equal
1817 \ = x1 x2 -- flag test x1=x2
1826 XOR #-1,TOS \ 1 flag Z = 1
1832 [IF] \ define IF and THEN
1833 \ https://forth-standard.org/standard/core/IF
1834 \ IF -- IFadr initialize conditional forward branch
1838 MOV &DP,TOS \ -- HERE
1839 ADD #4,&DP \ compile one word, reserve one word
1840 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
1841 ADD #2,TOS \ -- HERE+2=IFadr
1845 \ https://forth-standard.org/standard/core/THEN
1846 \ THEN IFadr -- resolve forward branch
1847 CODE THEN \ immediate
1848 MOV &DP,0(TOS) \ -- IFadr
1854 \ https://forth-standard.org/standard/core/ELSE
1855 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
1858 CODE ELSE \ immediate
1859 ADD #4,&DP \ make room to compile two words
1860 MOV &DP,W \ W=HERE+4
1862 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
1864 MOV W,TOS \ -- ELSEadr
1869 \ \ https://forth-standard.org/standard/core/DEFERStore
1870 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1872 \ [IF] \ define DEFER! and IS
1873 \ CODE DEFER! \ xt2 xt1 --
1874 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
1875 \ MOV @PSP+,TOS \ --
1879 \ \ https://forth-standard.org/standard/core/IS
1882 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
1883 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
1884 \ \ or in a definition : ... ['] U. IS DISPLAY ...
1885 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1887 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1891 \ IF POSTPONE ['] POSTPONE DEFER!
1897 \ https://forth-standard.org/standard/core/CR
1898 \ CR -- send CR+LF to the output device
1901 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
1902 CODE CR \ part I : DEFERed definition of CR
1903 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
1911 \ https://forth-standard.org/standard/core/toBODY
1912 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1922 BEGIN \ J_loop 8000 16000 24000 kHz
1923 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
1924 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
1936 \ \ if write : %xxxx_WWWW --
1937 \ \ if read : -- %0000_RRRR
1938 CODE TOP_LCD \ LCD Sample
1939 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1940 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1941 0= IF \ write LCD bits pattern
1943 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1944 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1947 THEN \ read LCD bits pattern
1950 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1951 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1956 CODE LCD_WRC \ char -- Write Char
1957 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1959 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
1960 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
1961 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1962 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1963 COLON \ high level word starts here
1964 TOP_LCD 2 20_US \ write high nibble first
1968 CODE LCD_WRF \ func -- Write Fonction
1969 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1973 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1974 : LCD_HOME $02 LCD_WRF 100 20_us ;
1976 \ CODE LCD_ENTRY_SET
1987 \ CODE LCD_DSP_SHIFT
1997 \ CODE LCD_CGRAM_SET
2007 \ CODE LCD_RDS \ -- status Read Status
2008 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2009 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2010 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2011 \ COLON \ starts a FORTH word
2012 \ TOP_LCD 2 20_us \ -- %0000_HHHH
2013 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
2014 \ HI2LO \ switch from FORTH to assembler
2015 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
2016 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
2017 \ MOV @RSP+,IP \ restore IP saved by COLON
2021 \ CODE LCD_RDC \ -- char Read Char
2022 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2027 \ ********************************\
2028 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2029 \ ********************************\
2030 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2031 BIT.B #SW2,&SW2_IN \ test switch S2
2032 0= IF \ case of switch S2 pressed
2033 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2035 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2038 BIT.B #SW1,&SW1_IN \ test switch S1 input
2039 0= IF \ case of Switch S1 pressed
2040 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2042 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2048 \ ********************************\
2050 \ ********************************\
2051 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
2052 \ ********************************\
2053 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2054 \ ********************************\
2055 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2056 \ \ SMclock = 8|16|24 MHz
2057 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2058 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2059 \ \ SR(9)=new Toggle bit memory (ADD on)
2060 \ ********************************\
2061 \ RC5_FirstStartBitHalfCycle: \
2062 \ ********************************\
2063 MOV #1778,X \ RC5_Period in us
2064 MOV #14,W \ count of loop
2066 \ ****************************\
2067 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2068 \ ****************************\ |
2069 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2070 \ RC5_Compute_3/4_Period: \ |
2071 RRUM #1,X \ X=1/2 cycle |
2074 ADD X,Y \ Y=3/4 cycle
2076 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2078 \ ****************************\
2079 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2080 \ ****************************\
2081 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2082 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2083 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2084 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2085 SUB #1,W \ decrement count loop
2086 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2087 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2088 0<> WHILE \ ----> out of loop ----+
2089 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2091 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2092 CMP Y,X \ 1 ^ | cycle time out of bound ?
2093 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
2094 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2096 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2097 \ ********************************\ |
2098 \ RC5_SampleEndOf: \ <---------------------+
2099 \ ********************************\
2100 BIC #$30,&RC5_TIM_CTL \ stop timer
2101 \ ********************************\
2102 \ RC5_ComputeNewRC5word \
2103 \ ********************************\
2104 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2105 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2106 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2107 \ ********************************\
2108 \ RC5_ComputeC6bit \
2109 \ ********************************\
2110 BIT #BIT14,T \ test /C6 bit in T
2111 0= IF BIS #BIT6,X \ set C6 bit in X
2112 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2113 \ ********************************\
2114 \ RC5_CommandByteIsDone \
2115 \ ********************************\
2116 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
2117 \ ********************************\
2118 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2119 XOR @RSP,T \ (new XOR old) Toggle bits
2120 BIT #UF10,T \ repeated RC5_command ?
2121 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
2122 XOR #UF10,0(RSP) \ 5 toggle bit memory
2123 \ ********************************\
2124 \ Display IR_RC5 code \
2125 \ ********************************\
2126 SUB #6,PSP \ -- x x x TOS
2127 MOV TOS,4(PSP) \ -- TOS x x TOS
2128 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
2129 MOV #$10,&BASEADR \ set hexadecimal base
2130 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
2131 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
2132 LO2HI \ switch from assembler to FORTH
2133 LCD_CLEAR \ set LCD cursor at home
2134 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
2135 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2136 TYPE \ -- TOS Base display "$xx" on LCD
2137 ['] EMIT >BODY IS EMIT \ restore EMIT
2138 HI2LO \ switch from FORTH to assembler
2139 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
2141 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
2142 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
2145 \ ********************************\
2147 \ define our STOP_APP
2148 \ ----------------------------------\
2149 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
2150 \ ----------------------------------\
2151 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
2152 0= IF \ only if START is done
2153 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
2154 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
2155 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
2156 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
2157 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
2159 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
2160 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2162 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
2164 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
2166 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
2167 MOV @W+,&IR_VEC \ restore Vector previous value
2169 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
2171 \ ----------------------------------\
2173 \ ----------------------------------\
2174 CODE STOP \ also called by INIT_R2L for some events
2175 \ ----------------------------------\
2179 ." type START to start RC5toLCD"
2181 \ ----------------------------------\
2183 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
2184 \ ----------------------------------\
2185 HDNCODE INIT_R2L \ called by START|SYS
2186 \ ----------------------------------\
2187 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2188 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2189 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2190 \ -- \ID input divider \ 10 = /4
2191 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2192 \ - \TBCLR TimerB Clear
2195 \ ----------------------------------\
2196 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2197 \ -- \CM Capture Mode
2202 \ --- \OUTMOD \ 011 = set/reset
2208 \ ----------------------------------\
2210 \ ----------------------------------\
2212 \ ----------------------------------\
2213 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2214 \ ----------------------------------\
2215 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
2216 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2217 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2220 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2221 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2225 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2226 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2228 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2229 \ ----------------------------------\
2230 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2231 \ ----------------------------------\
2232 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2233 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2234 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2235 \ ----------------------------------\
2236 BIS.B #LCDVo,&LCDVo_DIR \
2237 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2238 \ ----------------------------------\
2239 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2240 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2241 \ ----------------------------------\
2242 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2243 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2244 \ ----------------------------------\
2246 \ ----------------------------------\
2247 BIS.B #RC5,&IR_IE \ enable RC5_Int
2248 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2249 \ ----------------------------------\
2250 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2251 \ ----------------------------------\
2252 \ %01 0001 0100 \ TAxCTL
2253 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2254 \ -- \ ID divided by 1
2255 \ -- \ MC MODE = up to TAxCCRn
2256 \ - \ TACLR clear timer count
2259 \ ----------------------------------\
2260 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2261 \ ----------------------------------\
2263 \ --- \ TAIDEX pre divisor
2264 \ ----------------------------------\
2265 \ %0000 0000 0000 0101 \ TAxCCR0
2266 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2267 \ ----------------------------------\
2268 \ %0000 0000 0001 0000 \ TAxCCTL0
2269 \ - \ CAP capture/compare mode = compare
2272 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2273 \ ----------------------------------\
2275 \ ----------------------------------\
2276 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
2277 \ ----------------------------------\
2278 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
2279 \ ----------------------------------\
2280 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
2282 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
2283 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
2285 \ CMP #2,TOS \ Power_ON event
2286 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2287 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
2288 0= ?GOTO BW1 \ if yes run STOP.
2289 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
2290 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
2291 \ ----------------------------------\
2293 \ ----------------------------------\
2295 \ ----------------------------------\
2296 #1000 20_US \ 1- wait 20 ms
2297 %011 TOP_LCD \ 2- send DB5=DB4=1
2298 #205 20_US \ 3- wait 4,1 ms
2299 %011 TOP_LCD \ 4- send again DB5=DB4=1
2300 #5 20_US \ 5- wait 0,1 ms
2301 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2302 #2 20_US \ wait 40 us = LCD cycle
2303 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2304 #2 20_US \ wait 40 us = LCD cycle
2305 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2306 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2307 LCD_CLEAR \ 10- "LCD_Clear"
2308 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2309 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2310 LCD_CLEAR \ 10- "LCD_Clear"
2312 MOV @RSP+,PC \ RET to WARM|START
2314 \ ----------------------------------\
2316 \ ----------------------------------\
2317 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
2318 \ ----------------------------------\
2319 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
2321 MOV @IP+,PC \ does nothing if already initialised
2323 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
2324 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2326 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
2327 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
2329 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
2330 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
2332 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
2333 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2334 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
2335 MOV #RC5_INT,&IR_VEC \ init interrupt vector
2336 \ ----------------------------------\
2337 \ init 20 us count loop \ see 20_US
2338 \ ----------------------------------\ -- TOS
2339 SUB #6,PSP \ -- x x x TOS
2340 MOV TOS,4(PSP) \ -- TOS x x TOS
2341 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
2342 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
2343 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
2344 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
2345 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
2346 ADD #4,PSP \ -- TOS QUOThi
2347 MOV @PSP+,TOS \ -- TOS
2348 \ ----------------------------------\
2349 CALL #INIT_R2L \ run new INIT_HARD_APP
2351 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2352 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2353 \ CR ." I love you" \ display message on LCD
2354 \ ['] CR >BODY IS CR \ CR executes its default value
2355 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2356 ." RC5toLCD is running," \
2357 ." Type STOP to quit." \ display message on FastForth Terminal
2359 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
2361 \ ----------------------------------\
2365 MARKER {RC5TOLCD} \ restore the state before MARKER definition
2366 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
2367 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
2368 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
2369 \ {RC5TOLCD}+4 make room to save previous IR_VEC
2370 \ {RC5TOLCD}+6 make room for 20 us count loop.
2374 CODE TSTBIT \ addr bit_mask -- true/flase flag
2381 \ https://forth-standard.org/standard/core/Equal
2382 \ = x1 x2 -- flag test x1=x2
2391 XOR #-1,TOS \ 1 flag Z = 1
2397 [IF] \ define IF and THEN
2398 \ https://forth-standard.org/standard/core/IF
2399 \ IF -- IFadr initialize conditional forward branch
2403 MOV &DP,TOS \ -- HERE
2404 ADD #4,&DP \ compile one word, reserve one word
2405 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
2406 ADD #2,TOS \ -- HERE+2=IFadr
2410 \ https://forth-standard.org/standard/core/THEN
2411 \ THEN IFadr -- resolve forward branch
2412 CODE THEN \ immediate
2413 MOV &DP,0(TOS) \ -- IFadr
2419 \ https://forth-standard.org/standard/core/ELSE
2420 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
2423 CODE ELSE \ immediate
2424 ADD #4,&DP \ make room to compile two words
2425 MOV &DP,W \ W=HERE+4
2427 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
2429 MOV W,TOS \ -- ELSEadr
2434 \ \ https://forth-standard.org/standard/core/DEFERStore
2435 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2437 \ [IF] \ define DEFER! and IS
2438 \ CODE DEFER! \ xt2 xt1 --
2439 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
2440 \ MOV @PSP+,TOS \ --
2444 \ \ https://forth-standard.org/standard/core/IS
2447 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
2448 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
2449 \ \ or in a definition : ... ['] U. IS DISPLAY ...
2450 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2452 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2456 \ IF POSTPONE ['] POSTPONE DEFER!
2462 \ https://forth-standard.org/standard/core/CR
2463 \ CR -- send CR+LF to the output device
2466 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
2467 CODE CR \ part I : DEFERed definition of CR
2468 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
2476 \ https://forth-standard.org/standard/core/toBODY
2477 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2487 BEGIN \ J_loop 8000 16000 24000 kHz
2488 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
2489 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
2501 \ \ if write : %xxxx_WWWW --
2502 \ \ if read : -- %0000_RRRR
2503 CODE TOP_LCD \ LCD Sample
2504 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2505 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2506 0= IF \ write LCD bits pattern
2508 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2509 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2512 THEN \ read LCD bits pattern
2515 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2516 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2521 CODE LCD_WRC \ char -- Write Char
2522 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2524 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
2525 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
2526 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2527 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2528 COLON \ high level word starts here
2529 TOP_LCD 2 20_US \ write high nibble first
2533 CODE LCD_WRF \ func -- Write Fonction
2534 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2538 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
2539 : LCD_HOME $02 LCD_WRF 100 20_us ;
2541 \ CODE LCD_ENTRY_SET
2552 \ CODE LCD_DSP_SHIFT
2562 \ CODE LCD_CGRAM_SET
2572 \ CODE LCD_RDS \ -- status Read Status
2573 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2574 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2575 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2576 \ COLON \ starts a FORTH word
2577 \ TOP_LCD 2 20_us \ -- %0000_HHHH
2578 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
2579 \ HI2LO \ switch from FORTH to assembler
2580 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
2581 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
2582 \ MOV @RSP+,IP \ restore IP saved by COLON
2586 \ CODE LCD_RDC \ -- char Read Char
2587 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2592 \ ********************************\
2593 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2594 \ ********************************\
2595 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2596 BIT.B #SW2,&SW2_IN \ test switch S2
2597 0= IF \ case of switch S2 pressed
2598 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2600 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2603 BIT.B #SW1,&SW1_IN \ test switch S1 input
2604 0= IF \ case of Switch S1 pressed
2605 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2607 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2613 \ ********************************\
2615 \ ********************************\
2616 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
2617 \ ********************************\
2618 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2619 \ ********************************\
2620 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2621 \ \ SMclock = 8|16|24 MHz
2622 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2623 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2624 \ \ SR(9)=new Toggle bit memory (ADD on)
2625 \ ********************************\
2626 \ RC5_FirstStartBitHalfCycle: \
2627 \ ********************************\
2628 MOV #1778,X \ RC5_Period in us
2629 MOV #14,W \ count of loop
2631 \ ****************************\
2632 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2633 \ ****************************\ |
2634 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2635 \ RC5_Compute_3/4_Period: \ |
2636 RRUM #1,X \ X=1/2 cycle |
2639 ADD X,Y \ Y=3/4 cycle
2641 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2643 \ ****************************\
2644 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2645 \ ****************************\
2646 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2647 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2648 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2649 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2650 SUB #1,W \ decrement count loop
2651 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2652 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2653 0<> WHILE \ ----> out of loop ----+
2654 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2656 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2657 CMP Y,X \ 1 ^ | cycle time out of bound ?
2658 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
2659 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2661 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2662 \ ********************************\ |
2663 \ RC5_SampleEndOf: \ <---------------------+
2664 \ ********************************\
2665 BIC #$30,&RC5_TIM_CTL \ stop timer
2666 \ ********************************\
2667 \ RC5_ComputeNewRC5word \
2668 \ ********************************\
2669 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2670 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2671 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2672 \ ********************************\
2673 \ RC5_ComputeC6bit \
2674 \ ********************************\
2675 BIT #BIT14,T \ test /C6 bit in T
2676 0= IF BIS #BIT6,X \ set C6 bit in X
2677 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2678 \ ********************************\
2679 \ RC5_CommandByteIsDone \
2680 \ ********************************\
2681 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
2682 \ ********************************\
2683 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2684 XOR @RSP,T \ (new XOR old) Toggle bits
2685 BIT #UF10,T \ repeated RC5_command ?
2686 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
2687 XOR #UF10,0(RSP) \ 5 toggle bit memory
2688 \ ********************************\
2689 \ Display IR_RC5 code \
2690 \ ********************************\
2691 SUB #6,PSP \ -- x x x TOS
2692 MOV TOS,4(PSP) \ -- TOS x x TOS
2693 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
2694 MOV #$10,&BASEADR \ set hexadecimal base
2695 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
2696 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
2697 LO2HI \ switch from assembler to FORTH
2698 LCD_CLEAR \ set LCD cursor at home
2699 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
2700 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2701 TYPE \ -- TOS Base display "$xx" on LCD
2702 ['] EMIT >BODY IS EMIT \ restore EMIT
2703 HI2LO \ switch from FORTH to assembler
2704 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
2706 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
2707 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
2710 \ ********************************\
2712 \ define our STOP_APP
2713 \ ----------------------------------\
2714 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
2715 \ ----------------------------------\
2716 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
2717 0= IF \ only if START is done
2718 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
2719 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
2720 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
2721 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
2722 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
2724 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
2725 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2727 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
2729 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
2731 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
2732 MOV @W+,&IR_VEC \ restore Vector previous value
2734 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
2736 \ ----------------------------------\
2738 \ ----------------------------------\
2739 CODE STOP \ also called by INIT_R2L for some events
2740 \ ----------------------------------\
2744 ." type START to start RC5toLCD"
2746 \ ----------------------------------\
2748 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
2749 \ ----------------------------------\
2750 HDNCODE INIT_R2L \ called by START|SYS
2751 \ ----------------------------------\
2752 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2753 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2754 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2755 \ -- \ID input divider \ 10 = /4
2756 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2757 \ - \TBCLR TimerB Clear
2760 \ ----------------------------------\
2761 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2762 \ -- \CM Capture Mode
2767 \ --- \OUTMOD \ 011 = set/reset
2773 \ ----------------------------------\
2775 \ ----------------------------------\
2777 \ ----------------------------------\
2778 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2779 \ ----------------------------------\
2780 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
2781 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2782 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2785 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2786 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2790 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2791 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2793 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2794 \ ----------------------------------\
2795 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2796 \ ----------------------------------\
2797 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2798 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2799 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2800 \ ----------------------------------\
2801 BIS.B #LCDVo,&LCDVo_DIR \
2802 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2803 \ ----------------------------------\
2804 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2805 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2806 \ ----------------------------------\
2807 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2808 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2809 \ ----------------------------------\
2811 \ ----------------------------------\
2812 BIS.B #RC5,&IR_IE \ enable RC5_Int
2813 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2814 \ ----------------------------------\
2815 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2816 \ ----------------------------------\
2817 \ %01 0001 0100 \ TAxCTL
2818 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2819 \ -- \ ID divided by 1
2820 \ -- \ MC MODE = up to TAxCCRn
2821 \ - \ TACLR clear timer count
2824 \ ----------------------------------\
2825 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2826 \ ----------------------------------\
2828 \ --- \ TAIDEX pre divisor
2829 \ ----------------------------------\
2830 \ %0000 0000 0000 0101 \ TAxCCR0
2831 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2832 \ ----------------------------------\
2833 \ %0000 0000 0001 0000 \ TAxCCTL0
2834 \ - \ CAP capture/compare mode = compare
2837 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2838 \ ----------------------------------\
2840 \ ----------------------------------\
2841 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
2842 \ ----------------------------------\
2843 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
2844 \ ----------------------------------\
2845 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
2847 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
2848 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
2850 \ CMP #2,TOS \ Power_ON event
2851 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2852 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
2853 0= ?GOTO BW1 \ if yes run STOP.
2854 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
2855 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
2856 \ ----------------------------------\
2858 \ ----------------------------------\
2860 \ ----------------------------------\
2861 #1000 20_US \ 1- wait 20 ms
2862 %011 TOP_LCD \ 2- send DB5=DB4=1
2863 #205 20_US \ 3- wait 4,1 ms
2864 %011 TOP_LCD \ 4- send again DB5=DB4=1
2865 #5 20_US \ 5- wait 0,1 ms
2866 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2867 #2 20_US \ wait 40 us = LCD cycle
2868 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2869 #2 20_US \ wait 40 us = LCD cycle
2870 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2871 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2872 LCD_CLEAR \ 10- "LCD_Clear"
2873 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2874 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2875 LCD_CLEAR \ 10- "LCD_Clear"
2877 MOV @RSP+,PC \ RET to WARM|START
2879 \ ----------------------------------\
2881 \ ----------------------------------\
2882 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
2883 \ ----------------------------------\
2884 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
2886 MOV @IP+,PC \ does nothing if already initialised
2888 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
2889 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2891 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
2892 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
2894 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
2895 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
2897 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
2898 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2899 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
2900 MOV #RC5_INT,&IR_VEC \ init interrupt vector
2901 \ ----------------------------------\
2902 \ init 20 us count loop \ see 20_US
2903 \ ----------------------------------\ -- TOS
2904 SUB #6,PSP \ -- x x x TOS
2905 MOV TOS,4(PSP) \ -- TOS x x TOS
2906 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
2907 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
2908 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
2909 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
2910 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
2911 ADD #4,PSP \ -- TOS QUOThi
2912 MOV @PSP+,TOS \ -- TOS
2913 \ ----------------------------------\
2914 CALL #INIT_R2L \ run new INIT_HARD_APP
2916 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2917 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2918 \ CR ." I love you" \ display message on LCD
2919 \ ['] CR >BODY IS CR \ CR executes its default value
2920 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2921 ." RC5toLCD is running," \
2922 ." Type STOP to quit." \ display message on FastForth Terminal
2924 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
2926 \ ----------------------------------\
2930 MARKER {RC5TOLCD} \ restore the state before MARKER definition
2931 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
2932 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
2933 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
2934 \ {RC5TOLCD}+4 make room to save previous IR_VEC
2935 \ {RC5TOLCD}+6 make room for 20 us count loop.
2939 CODE TSTBIT \ addr bit_mask -- true/flase flag
2946 \ https://forth-standard.org/standard/core/Equal
2947 \ = x1 x2 -- flag test x1=x2
2956 XOR #-1,TOS \ 1 flag Z = 1
2962 [IF] \ define IF and THEN
2963 \ https://forth-standard.org/standard/core/IF
2964 \ IF -- IFadr initialize conditional forward branch
2968 MOV &DP,TOS \ -- HERE
2969 ADD #4,&DP \ compile one word, reserve one word
2970 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
2971 ADD #2,TOS \ -- HERE+2=IFadr
2975 \ https://forth-standard.org/standard/core/THEN
2976 \ THEN IFadr -- resolve forward branch
2977 CODE THEN \ immediate
2978 MOV &DP,0(TOS) \ -- IFadr
2984 \ https://forth-standard.org/standard/core/ELSE
2985 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
2988 CODE ELSE \ immediate
2989 ADD #4,&DP \ make room to compile two words
2990 MOV &DP,W \ W=HERE+4
2992 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
2994 MOV W,TOS \ -- ELSEadr
2999 \ \ https://forth-standard.org/standard/core/DEFERStore
3000 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3002 \ [IF] \ define DEFER! and IS
3003 \ CODE DEFER! \ xt2 xt1 --
3004 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
3005 \ MOV @PSP+,TOS \ --
3009 \ \ https://forth-standard.org/standard/core/IS
3012 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
3013 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
3014 \ \ or in a definition : ... ['] U. IS DISPLAY ...
3015 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3017 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3021 \ IF POSTPONE ['] POSTPONE DEFER!
3027 \ https://forth-standard.org/standard/core/CR
3028 \ CR -- send CR+LF to the output device
3031 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
3032 CODE CR \ part I : DEFERed definition of CR
3033 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
3041 \ https://forth-standard.org/standard/core/toBODY
3042 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3052 BEGIN \ J_loop 8000 16000 24000 kHz
3053 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
3054 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
3066 \ \ if write : %xxxx_WWWW --
3067 \ \ if read : -- %0000_RRRR
3068 CODE TOP_LCD \ LCD Sample
3069 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3070 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3071 0= IF \ write LCD bits pattern
3073 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3074 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3077 THEN \ read LCD bits pattern
3080 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3081 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3086 CODE LCD_WRC \ char -- Write Char
3087 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3089 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
3090 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
3091 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3092 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3093 COLON \ high level word starts here
3094 TOP_LCD 2 20_US \ write high nibble first
3098 CODE LCD_WRF \ func -- Write Fonction
3099 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3103 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3104 : LCD_HOME $02 LCD_WRF 100 20_us ;
3106 \ CODE LCD_ENTRY_SET
3117 \ CODE LCD_DSP_SHIFT
3127 \ CODE LCD_CGRAM_SET
3137 \ CODE LCD_RDS \ -- status Read Status
3138 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3139 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3140 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3141 \ COLON \ starts a FORTH word
3142 \ TOP_LCD 2 20_us \ -- %0000_HHHH
3143 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
3144 \ HI2LO \ switch from FORTH to assembler
3145 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
3146 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
3147 \ MOV @RSP+,IP \ restore IP saved by COLON
3151 \ CODE LCD_RDC \ -- char Read Char
3152 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3157 \ ********************************\
3158 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3159 \ ********************************\
3160 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3161 BIT.B #SW2,&SW2_IN \ test switch S2
3162 0= IF \ case of switch S2 pressed
3163 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3165 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3168 BIT.B #SW1,&SW1_IN \ test switch S1 input
3169 0= IF \ case of Switch S1 pressed
3170 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3172 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3178 \ ********************************\
3180 \ ********************************\
3181 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
3182 \ ********************************\
3183 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3184 \ ********************************\
3185 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3186 \ \ SMclock = 8|16|24 MHz
3187 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3188 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3189 \ \ SR(9)=new Toggle bit memory (ADD on)
3190 \ ********************************\
3191 \ RC5_FirstStartBitHalfCycle: \
3192 \ ********************************\
3193 MOV #1778,X \ RC5_Period in us
3194 MOV #14,W \ count of loop
3196 \ ****************************\
3197 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3198 \ ****************************\ |
3199 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3200 \ RC5_Compute_3/4_Period: \ |
3201 RRUM #1,X \ X=1/2 cycle |
3204 ADD X,Y \ Y=3/4 cycle
3206 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3208 \ ****************************\
3209 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3210 \ ****************************\
3211 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3212 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3213 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3214 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3215 SUB #1,W \ decrement count loop
3216 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3217 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3218 0<> WHILE \ ----> out of loop ----+
3219 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3221 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3222 CMP Y,X \ 1 ^ | cycle time out of bound ?
3223 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
3224 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3226 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3227 \ ********************************\ |
3228 \ RC5_SampleEndOf: \ <---------------------+
3229 \ ********************************\
3230 BIC #$30,&RC5_TIM_CTL \ stop timer
3231 \ ********************************\
3232 \ RC5_ComputeNewRC5word \
3233 \ ********************************\
3234 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3235 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3236 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3237 \ ********************************\
3238 \ RC5_ComputeC6bit \
3239 \ ********************************\
3240 BIT #BIT14,T \ test /C6 bit in T
3241 0= IF BIS #BIT6,X \ set C6 bit in X
3242 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3243 \ ********************************\
3244 \ RC5_CommandByteIsDone \
3245 \ ********************************\
3246 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
3247 \ ********************************\
3248 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3249 XOR @RSP,T \ (new XOR old) Toggle bits
3250 BIT #UF10,T \ repeated RC5_command ?
3251 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
3252 XOR #UF10,0(RSP) \ 5 toggle bit memory
3253 \ ********************************\
3254 \ Display IR_RC5 code \
3255 \ ********************************\
3256 SUB #6,PSP \ -- x x x TOS
3257 MOV TOS,4(PSP) \ -- TOS x x TOS
3258 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
3259 MOV #$10,&BASEADR \ set hexadecimal base
3260 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
3261 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
3262 LO2HI \ switch from assembler to FORTH
3263 LCD_CLEAR \ set LCD cursor at home
3264 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
3265 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3266 TYPE \ -- TOS Base display "$xx" on LCD
3267 ['] EMIT >BODY IS EMIT \ restore EMIT
3268 HI2LO \ switch from FORTH to assembler
3269 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
3271 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
3272 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
3275 \ ********************************\
3277 \ define our STOP_APP
3278 \ ----------------------------------\
3279 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
3280 \ ----------------------------------\
3281 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
3282 0= IF \ only if START is done
3283 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
3284 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
3285 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
3286 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
3287 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
3289 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
3290 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
3292 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
3294 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
3296 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
3297 MOV @W+,&IR_VEC \ restore Vector previous value
3299 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
3301 \ ----------------------------------\
3303 \ ----------------------------------\
3304 CODE STOP \ also called by INIT_R2L for some events
3305 \ ----------------------------------\
3309 ." type START to start RC5toLCD"
3311 \ ----------------------------------\
3313 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
3314 \ ----------------------------------\
3315 HDNCODE INIT_R2L \ called by START|SYS
3316 \ ----------------------------------\
3317 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3318 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3319 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3320 \ -- \ID input divider \ 10 = /4
3321 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3322 \ - \TBCLR TimerB Clear
3325 \ ----------------------------------\
3326 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3327 \ -- \CM Capture Mode
3332 \ --- \OUTMOD \ 011 = set/reset
3338 \ ----------------------------------\
3340 \ ----------------------------------\
3342 \ ----------------------------------\
3343 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3344 \ ----------------------------------\
3345 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
3346 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3347 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3350 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3351 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3355 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3356 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3358 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3359 \ ----------------------------------\
3360 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3361 \ ----------------------------------\
3362 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3363 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3364 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3365 \ ----------------------------------\
3366 BIS.B #LCDVo,&LCDVo_DIR \
3367 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3368 \ ----------------------------------\
3369 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3370 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3371 \ ----------------------------------\
3372 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3373 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3374 \ ----------------------------------\
3376 \ ----------------------------------\
3377 BIS.B #RC5,&IR_IE \ enable RC5_Int
3378 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3379 \ ----------------------------------\
3380 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3381 \ ----------------------------------\
3382 \ %01 0001 0100 \ TAxCTL
3383 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3384 \ -- \ ID divided by 1
3385 \ -- \ MC MODE = up to TAxCCRn
3386 \ - \ TACLR clear timer count
3389 \ ----------------------------------\
3390 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3391 \ ----------------------------------\
3393 \ --- \ TAIDEX pre divisor
3394 \ ----------------------------------\
3395 \ %0000 0000 0000 0101 \ TAxCCR0
3396 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3397 \ ----------------------------------\
3398 \ %0000 0000 0001 0000 \ TAxCCTL0
3399 \ - \ CAP capture/compare mode = compare
3402 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3403 \ ----------------------------------\
3405 \ ----------------------------------\
3406 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
3407 \ ----------------------------------\
3408 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
3409 \ ----------------------------------\
3410 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
3412 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
3413 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
3415 \ CMP #2,TOS \ Power_ON event
3416 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3417 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
3418 0= ?GOTO BW1 \ if yes run STOP.
3419 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
3420 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
3421 \ ----------------------------------\
3423 \ ----------------------------------\
3425 \ ----------------------------------\
3426 #1000 20_US \ 1- wait 20 ms
3427 %011 TOP_LCD \ 2- send DB5=DB4=1
3428 #205 20_US \ 3- wait 4,1 ms
3429 %011 TOP_LCD \ 4- send again DB5=DB4=1
3430 #5 20_US \ 5- wait 0,1 ms
3431 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3432 #2 20_US \ wait 40 us = LCD cycle
3433 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3434 #2 20_US \ wait 40 us = LCD cycle
3435 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3436 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3437 LCD_CLEAR \ 10- "LCD_Clear"
3438 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3439 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3440 LCD_CLEAR \ 10- "LCD_Clear"
3442 MOV @RSP+,PC \ RET to WARM|START
3444 \ ----------------------------------\
3446 \ ----------------------------------\
3447 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
3448 \ ----------------------------------\
3449 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
3451 MOV @IP+,PC \ does nothing if already initialised
3453 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
3454 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
3456 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
3457 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
3459 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
3460 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
3462 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
3463 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3464 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
3465 MOV #RC5_INT,&IR_VEC \ init interrupt vector
3466 \ ----------------------------------\
3467 \ init 20 us count loop \ see 20_US
3468 \ ----------------------------------\ -- TOS
3469 SUB #6,PSP \ -- x x x TOS
3470 MOV TOS,4(PSP) \ -- TOS x x TOS
3471 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
3472 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
3473 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
3474 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
3475 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
3476 ADD #4,PSP \ -- TOS QUOThi
3477 MOV @PSP+,TOS \ -- TOS
3478 \ ----------------------------------\
3479 CALL #INIT_R2L \ run new INIT_HARD_APP
3481 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3482 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3483 \ CR ." I love you" \ display message on LCD
3484 \ ['] CR >BODY IS CR \ CR executes its default value
3485 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3486 ." RC5toLCD is running," \
3487 ." Type STOP to quit." \ display message on FastForth Terminal
3489 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
3491 \ ----------------------------------\
3495 MARKER {RC5TOLCD} \ restore the state before MARKER definition
3496 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
3497 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
3498 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
3499 \ {RC5TOLCD}+4 make room to save previous IR_VEC
3500 \ {RC5TOLCD}+6 make room for 20 us count loop.
3504 CODE TSTBIT \ addr bit_mask -- true/flase flag
3511 \ https://forth-standard.org/standard/core/Equal
3512 \ = x1 x2 -- flag test x1=x2
3521 XOR #-1,TOS \ 1 flag Z = 1
3527 [IF] \ define IF and THEN
3528 \ https://forth-standard.org/standard/core/IF
3529 \ IF -- IFadr initialize conditional forward branch
3533 MOV &DP,TOS \ -- HERE
3534 ADD #4,&DP \ compile one word, reserve one word
3535 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
3536 ADD #2,TOS \ -- HERE+2=IFadr
3540 \ https://forth-standard.org/standard/core/THEN
3541 \ THEN IFadr -- resolve forward branch
3542 CODE THEN \ immediate
3543 MOV &DP,0(TOS) \ -- IFadr
3549 \ https://forth-standard.org/standard/core/ELSE
3550 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
3553 CODE ELSE \ immediate
3554 ADD #4,&DP \ make room to compile two words
3555 MOV &DP,W \ W=HERE+4
3557 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
3559 MOV W,TOS \ -- ELSEadr
3564 \ \ https://forth-standard.org/standard/core/DEFERStore
3565 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3567 \ [IF] \ define DEFER! and IS
3568 \ CODE DEFER! \ xt2 xt1 --
3569 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
3570 \ MOV @PSP+,TOS \ --
3574 \ \ https://forth-standard.org/standard/core/IS
3577 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
3578 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
3579 \ \ or in a definition : ... ['] U. IS DISPLAY ...
3580 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3582 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3586 \ IF POSTPONE ['] POSTPONE DEFER!
3592 \ https://forth-standard.org/standard/core/CR
3593 \ CR -- send CR+LF to the output device
3596 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
3597 CODE CR \ part I : DEFERed definition of CR
3598 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
3606 \ https://forth-standard.org/standard/core/toBODY
3607 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3617 BEGIN \ J_loop 8000 16000 24000 kHz
3618 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
3619 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
3631 \ \ if write : %xxxx_WWWW --
3632 \ \ if read : -- %0000_RRRR
3633 CODE TOP_LCD \ LCD Sample
3634 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3635 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3636 0= IF \ write LCD bits pattern
3638 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3639 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3642 THEN \ read LCD bits pattern
3645 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3646 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3651 CODE LCD_WRC \ char -- Write Char
3652 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3654 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
3655 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
3656 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3657 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3658 COLON \ high level word starts here
3659 TOP_LCD 2 20_US \ write high nibble first
3663 CODE LCD_WRF \ func -- Write Fonction
3664 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3668 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3669 : LCD_HOME $02 LCD_WRF 100 20_us ;
3671 \ CODE LCD_ENTRY_SET
3682 \ CODE LCD_DSP_SHIFT
3692 \ CODE LCD_CGRAM_SET
3702 \ CODE LCD_RDS \ -- status Read Status
3703 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3704 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3705 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3706 \ COLON \ starts a FORTH word
3707 \ TOP_LCD 2 20_us \ -- %0000_HHHH
3708 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
3709 \ HI2LO \ switch from FORTH to assembler
3710 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
3711 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
3712 \ MOV @RSP+,IP \ restore IP saved by COLON
3716 \ CODE LCD_RDC \ -- char Read Char
3717 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3722 \ ********************************\
3723 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3724 \ ********************************\
3725 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3726 BIT.B #SW2,&SW2_IN \ test switch S2
3727 0= IF \ case of switch S2 pressed
3728 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3730 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3733 BIT.B #SW1,&SW1_IN \ test switch S1 input
3734 0= IF \ case of Switch S1 pressed
3735 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3737 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3743 \ ********************************\
3745 \ ********************************\
3746 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
3747 \ ********************************\
3748 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3749 \ ********************************\
3750 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3751 \ \ SMclock = 8|16|24 MHz
3752 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3753 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3754 \ \ SR(9)=new Toggle bit memory (ADD on)
3755 \ ********************************\
3756 \ RC5_FirstStartBitHalfCycle: \
3757 \ ********************************\
3758 MOV #1778,X \ RC5_Period in us
3759 MOV #14,W \ count of loop
3761 \ ****************************\
3762 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3763 \ ****************************\ |
3764 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3765 \ RC5_Compute_3/4_Period: \ |
3766 RRUM #1,X \ X=1/2 cycle |
3769 ADD X,Y \ Y=3/4 cycle
3771 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3773 \ ****************************\
3774 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3775 \ ****************************\
3776 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3777 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3778 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3779 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3780 SUB #1,W \ decrement count loop
3781 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3782 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3783 0<> WHILE \ ----> out of loop ----+
3784 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3786 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3787 CMP Y,X \ 1 ^ | cycle time out of bound ?
3788 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
3789 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3791 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3792 \ ********************************\ |
3793 \ RC5_SampleEndOf: \ <---------------------+
3794 \ ********************************\
3795 BIC #$30,&RC5_TIM_CTL \ stop timer
3796 \ ********************************\
3797 \ RC5_ComputeNewRC5word \
3798 \ ********************************\
3799 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3800 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3801 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3802 \ ********************************\
3803 \ RC5_ComputeC6bit \
3804 \ ********************************\
3805 BIT #BIT14,T \ test /C6 bit in T
3806 0= IF BIS #BIT6,X \ set C6 bit in X
3807 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3808 \ ********************************\
3809 \ RC5_CommandByteIsDone \
3810 \ ********************************\
3811 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
3812 \ ********************************\
3813 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3814 XOR @RSP,T \ (new XOR old) Toggle bits
3815 BIT #UF10,T \ repeated RC5_command ?
3816 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
3817 XOR #UF10,0(RSP) \ 5 toggle bit memory
3818 \ ********************************\
3819 \ Display IR_RC5 code \
3820 \ ********************************\
3821 SUB #6,PSP \ -- x x x TOS
3822 MOV TOS,4(PSP) \ -- TOS x x TOS
3823 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
3824 MOV #$10,&BASEADR \ set hexadecimal base
3825 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
3826 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
3827 LO2HI \ switch from assembler to FORTH
3828 LCD_CLEAR \ set LCD cursor at home
3829 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
3830 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3831 TYPE \ -- TOS Base display "$xx" on LCD
3832 ['] EMIT >BODY IS EMIT \ restore EMIT
3833 HI2LO \ switch from FORTH to assembler
3834 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
3836 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
3837 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
3840 \ ********************************\
3842 \ define our STOP_APP
3843 \ ----------------------------------\
3844 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
3845 \ ----------------------------------\
3846 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
3847 0= IF \ only if START is done
3848 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
3849 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
3850 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
3851 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
3852 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
3854 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
3855 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
3857 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
3859 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
3861 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
3862 MOV @W+,&IR_VEC \ restore Vector previous value
3864 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
3866 \ ----------------------------------\
3868 \ ----------------------------------\
3869 CODE STOP \ also called by INIT_R2L for some events
3870 \ ----------------------------------\
3874 ." type START to start RC5toLCD"
3876 \ ----------------------------------\
3878 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
3879 \ ----------------------------------\
3880 HDNCODE INIT_R2L \ called by START|SYS
3881 \ ----------------------------------\
3882 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3883 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3884 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3885 \ -- \ID input divider \ 10 = /4
3886 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3887 \ - \TBCLR TimerB Clear
3890 \ ----------------------------------\
3891 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3892 \ -- \CM Capture Mode
3897 \ --- \OUTMOD \ 011 = set/reset
3903 \ ----------------------------------\
3905 \ ----------------------------------\
3907 \ ----------------------------------\
3908 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3909 \ ----------------------------------\
3910 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
3911 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3912 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3915 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3916 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3920 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3921 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3923 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3924 \ ----------------------------------\
3925 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3926 \ ----------------------------------\
3927 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3928 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3929 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3930 \ ----------------------------------\
3931 BIS.B #LCDVo,&LCDVo_DIR \
3932 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3933 \ ----------------------------------\
3934 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3935 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3936 \ ----------------------------------\
3937 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3938 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3939 \ ----------------------------------\
3941 \ ----------------------------------\
3942 BIS.B #RC5,&IR_IE \ enable RC5_Int
3943 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3944 \ ----------------------------------\
3945 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3946 \ ----------------------------------\
3947 \ %01 0001 0100 \ TAxCTL
3948 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3949 \ -- \ ID divided by 1
3950 \ -- \ MC MODE = up to TAxCCRn
3951 \ - \ TACLR clear timer count
3954 \ ----------------------------------\
3955 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3956 \ ----------------------------------\
3958 \ --- \ TAIDEX pre divisor
3959 \ ----------------------------------\
3960 \ %0000 0000 0000 0101 \ TAxCCR0
3961 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3962 \ ----------------------------------\
3963 \ %0000 0000 0001 0000 \ TAxCCTL0
3964 \ - \ CAP capture/compare mode = compare
3967 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3968 \ ----------------------------------\
3970 \ ----------------------------------\
3971 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
3972 \ ----------------------------------\
3973 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
3974 \ ----------------------------------\
3975 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
3977 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
3978 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
3980 \ CMP #2,TOS \ Power_ON event
3981 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3982 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
3983 0= ?GOTO BW1 \ if yes run STOP.
3984 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
3985 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
3986 \ ----------------------------------\
3988 \ ----------------------------------\
3990 \ ----------------------------------\
3991 #1000 20_US \ 1- wait 20 ms
3992 %011 TOP_LCD \ 2- send DB5=DB4=1
3993 #205 20_US \ 3- wait 4,1 ms
3994 %011 TOP_LCD \ 4- send again DB5=DB4=1
3995 #5 20_US \ 5- wait 0,1 ms
3996 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3997 #2 20_US \ wait 40 us = LCD cycle
3998 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3999 #2 20_US \ wait 40 us = LCD cycle
4000 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4001 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4002 LCD_CLEAR \ 10- "LCD_Clear"
4003 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4004 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4005 LCD_CLEAR \ 10- "LCD_Clear"
4007 MOV @RSP+,PC \ RET to WARM|START
4009 \ ----------------------------------\
4011 \ ----------------------------------\
4012 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
4013 \ ----------------------------------\
4014 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
4016 MOV @IP+,PC \ does nothing if already initialised
4018 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
4019 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
4021 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
4022 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
4024 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
4025 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
4027 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
4028 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4029 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
4030 MOV #RC5_INT,&IR_VEC \ init interrupt vector
4031 \ ----------------------------------\
4032 \ init 20 us count loop \ see 20_US
4033 \ ----------------------------------\ -- TOS
4034 SUB #6,PSP \ -- x x x TOS
4035 MOV TOS,4(PSP) \ -- TOS x x TOS
4036 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
4037 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
4038 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
4039 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
4040 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
4041 ADD #4,PSP \ -- TOS QUOThi
4042 MOV @PSP+,TOS \ -- TOS
4043 \ ----------------------------------\
4044 CALL #INIT_R2L \ run new INIT_HARD_APP
4046 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4047 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4048 \ CR ." I love you" \ display message on LCD
4049 \ ['] CR >BODY IS CR \ CR executes its default value
4050 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4051 ." RC5toLCD is running," \
4052 ." Type STOP to quit." \ display message on FastForth Terminal
4054 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
4056 \ ----------------------------------\
4060 MARKER {RC5TOLCD} \ restore the state before MARKER definition
4061 \ \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
4062 8 ALLOT \ {UARTI2CS} make room to save previous INI_APP address
4063 \ {RC5TOLCD}+2 make room to save previous WDT_TIM_0_VEC
4064 \ {RC5TOLCD}+4 make room to save previous IR_VEC
4065 \ {RC5TOLCD}+6 make room for 20 us count loop.
4069 CODE TSTBIT \ addr bit_mask -- true/flase flag
4076 \ https://forth-standard.org/standard/core/Equal
4077 \ = x1 x2 -- flag test x1=x2
4086 XOR #-1,TOS \ 1 flag Z = 1
4092 [IF] \ define IF and THEN
4093 \ https://forth-standard.org/standard/core/IF
4094 \ IF -- IFadr initialize conditional forward branch
4098 MOV &DP,TOS \ -- HERE
4099 ADD #4,&DP \ compile one word, reserve one word
4100 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
4101 ADD #2,TOS \ -- HERE+2=IFadr
4105 \ https://forth-standard.org/standard/core/THEN
4106 \ THEN IFadr -- resolve forward branch
4107 CODE THEN \ immediate
4108 MOV &DP,0(TOS) \ -- IFadr
4114 \ https://forth-standard.org/standard/core/ELSE
4115 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
4118 CODE ELSE \ immediate
4119 ADD #4,&DP \ make room to compile two words
4120 MOV &DP,W \ W=HERE+4
4122 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
4124 MOV W,TOS \ -- ELSEadr
4129 \ \ https://forth-standard.org/standard/core/DEFERStore
4130 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
4132 \ [IF] \ define DEFER! and IS
4133 \ CODE DEFER! \ xt2 xt1 --
4134 \ MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
4135 \ MOV @PSP+,TOS \ --
4139 \ \ https://forth-standard.org/standard/core/IS
4142 \ \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
4143 \ \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
4144 \ \ or in a definition : ... ['] U. IS DISPLAY ...
4145 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
4147 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
4151 \ IF POSTPONE ['] POSTPONE DEFER!
4157 \ https://forth-standard.org/standard/core/CR
4158 \ CR -- send CR+LF to the output device
4161 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
4162 CODE CR \ part I : DEFERed definition of CR
4163 MOV #NEXT_ADR,PC \ [PFA] = NEXT_ADR
4171 \ https://forth-standard.org/standard/core/toBODY
4172 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
4182 BEGIN \ J_loop 8000 16000 24000 kHz
4183 MOV &{RC5TOLCD}+6,X \ 3 X = {40 80 120}
4184 SUB #2,X \ +1 X = {38 78 118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
4196 \ \ if write : %xxxx_WWWW --
4197 \ \ if read : -- %0000_RRRR
4198 CODE TOP_LCD \ LCD Sample
4199 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4200 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4201 0= IF \ write LCD bits pattern
4203 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4204 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4207 THEN \ read LCD bits pattern
4210 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4211 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4216 CODE LCD_WRC \ char -- Write Char
4217 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4219 MOV TOS,0(PSP) \ -- %HHHH_LLLL %HHHH_LLLL
4220 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
4221 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4222 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4223 COLON \ high level word starts here
4224 TOP_LCD 2 20_US \ write high nibble first
4228 CODE LCD_WRF \ func -- Write Fonction
4229 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4233 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4234 : LCD_HOME $02 LCD_WRF 100 20_us ;
4236 \ CODE LCD_ENTRY_SET
4247 \ CODE LCD_DSP_SHIFT
4257 \ CODE LCD_CGRAM_SET
4267 \ CODE LCD_RDS \ -- status Read Status
4268 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4269 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4270 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4271 \ COLON \ starts a FORTH word
4272 \ TOP_LCD 2 20_us \ -- %0000_HHHH
4273 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
4274 \ HI2LO \ switch from FORTH to assembler
4275 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
4276 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
4277 \ MOV @RSP+,IP \ restore IP saved by COLON
4281 \ CODE LCD_RDC \ -- char Read Char
4282 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4287 \ ********************************\
4288 HDNCODE WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4289 \ ********************************\
4290 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4291 BIT.B #SW2,&SW2_IN \ test switch S2
4292 0= IF \ case of switch S2 pressed
4293 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4295 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4298 BIT.B #SW1,&SW1_IN \ test switch S1 input
4299 0= IF \ case of Switch S1 pressed
4300 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4302 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4308 \ ********************************\
4310 \ ********************************\
4311 HDNCODE RC5_INT \ wake up on Px.RC5 change interrupt
4312 \ ********************************\
4313 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4314 \ ********************************\
4315 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4316 \ \ SMclock = 8|16|24 MHz
4317 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4318 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4319 \ \ SR(9)=new Toggle bit memory (ADD on)
4320 \ ********************************\
4321 \ RC5_FirstStartBitHalfCycle: \
4322 \ ********************************\
4323 MOV #1778,X \ RC5_Period in us
4324 MOV #14,W \ count of loop
4326 \ ****************************\
4327 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4328 \ ****************************\ |
4329 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4330 \ RC5_Compute_3/4_Period: \ |
4331 RRUM #1,X \ X=1/2 cycle |
4334 ADD X,Y \ Y=3/4 cycle
4336 CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4338 \ ****************************\
4339 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4340 \ ****************************\
4341 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4342 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4343 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4344 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4345 SUB #1,W \ decrement count loop
4346 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4347 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4348 0<> WHILE \ ----> out of loop ----+
4349 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4351 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4352 CMP Y,X \ 1 ^ | cycle time out of bound ?
4353 U>= ?GOTO FW1 \ | | quit on truncated RC5 message
4354 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4356 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4357 \ ********************************\ |
4358 \ RC5_SampleEndOf: \ <---------------------+
4359 \ ********************************\
4360 BIC #$30,&RC5_TIM_CTL \ stop timer
4361 \ ********************************\
4362 \ RC5_ComputeNewRC5word \
4363 \ ********************************\
4364 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4365 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4366 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4367 \ ********************************\
4368 \ RC5_ComputeC6bit \
4369 \ ********************************\
4370 BIT #BIT14,T \ test /C6 bit in T
4371 0= IF BIS #BIT6,X \ set C6 bit in X
4372 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4373 \ ********************************\
4374 \ RC5_CommandByteIsDone \
4375 \ ********************************\
4376 \ Only New_RC5_Command ADD_ON \ use SR(10) bit as toggle bit
4377 \ ********************************\
4378 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4379 XOR @RSP,T \ (new XOR old) Toggle bits
4380 BIT #UF10,T \ repeated RC5_command ?
4381 0= ?GOTO FW2 \ yes, RETI without UF10 change and without action !
4382 XOR #UF10,0(RSP) \ 5 toggle bit memory
4383 \ ********************************\
4384 \ Display IR_RC5 code \
4385 \ ********************************\
4386 SUB #6,PSP \ -- x x x TOS
4387 MOV TOS,4(PSP) \ -- TOS x x TOS
4388 MOV &BASEADR,2(PSP) \ -- TOS Base x TOS
4389 MOV #$10,&BASEADR \ set hexadecimal base
4390 MOV X,0(PSP) \ -- TOS Base RC5_code TOS convert number to ascii low word = RC5 byte
4391 MOV #0,TOS \ -- TOS Base RC5_code 0 convert double number to ascii
4392 LO2HI \ switch from assembler to FORTH
4393 LCD_CLEAR \ set LCD cursor at home
4394 <# # #S #36 HOLD #> \ -- TOS Base adr cnt 32 bits conversion as "$xx"
4395 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4396 TYPE \ -- TOS Base display "$xx" on LCD
4397 ['] EMIT >BODY IS EMIT \ restore EMIT
4398 HI2LO \ switch from FORTH to assembler
4399 MOV @PSP+,&BASEADR \ -- TOS restore current BASE
4401 FW1 BIC #$30,&RC5_TIM_CTL \ stop timer (case of truncated RC5 message)
4402 FW2 BIC #%1111_1000,0(RSP) \ force CPU Active Mode and disable GIE in saved SR
4405 \ ********************************\
4407 \ define our STOP_APP
4408 \ ----------------------------------\
4409 HDNCODE STOP_R2L \ called by STOP|INIT_R2L|{RC5TOLCD}
4410 \ ----------------------------------\
4411 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
4412 0= IF \ only if START is done
4413 BIC.B #RC5,&IR_IE \ clear I/O RC5_Int
4414 BIC.B #RC5,&IR_IFG \ clear I/O RC5_Int flag
4415 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER, clear LCD_TIMER IFG
4416 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
4417 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
4419 MOV #RET_ADR,-2(W) \ clear MARKER_DOES call
4420 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
4422 MOV @W+,&UART_WARM+2 \ restore previous ini_APP
4424 MOV @W+,&I2C_WARM+2 \ restore previous ini_APP
4426 MOV @W+,&WDT_TIM_0_VEC \ restore Vector previous value
4427 MOV @W+,&IR_VEC \ restore Vector previous value
4429 MOV @RSP+,PC \ RET to STOP|WARM+4|{RC5TOLCD}
4431 \ ----------------------------------\
4433 \ ----------------------------------\
4434 CODE STOP \ also called by INIT_R2L for some events
4435 \ ----------------------------------\
4439 ." type START to start RC5toLCD"
4441 \ ----------------------------------\
4443 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
4444 \ ----------------------------------\
4445 HDNCODE INIT_R2L \ called by START|SYS
4446 \ ----------------------------------\
4447 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4448 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4449 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4450 \ -- \ID input divider \ 10 = /4
4451 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4452 \ - \TBCLR TimerB Clear
4455 \ ----------------------------------\
4456 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4457 \ -- \CM Capture Mode
4462 \ --- \OUTMOD \ 011 = set/reset
4468 \ ----------------------------------\
4470 \ ----------------------------------\
4472 \ ----------------------------------\
4473 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4474 \ ----------------------------------\
4475 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
4476 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4477 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4480 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4481 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4485 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4486 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4488 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4489 \ ----------------------------------\
4490 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4491 \ ----------------------------------\
4492 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4493 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4494 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4495 \ ----------------------------------\
4496 BIS.B #LCDVo,&LCDVo_DIR \
4497 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4498 \ ----------------------------------\
4499 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4500 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4501 \ ----------------------------------\
4502 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4503 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4504 \ ----------------------------------\
4506 \ ----------------------------------\
4507 BIS.B #RC5,&IR_IE \ enable RC5_Int
4508 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4509 \ ----------------------------------\
4510 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4511 \ ----------------------------------\
4512 \ %01 0001 0100 \ TAxCTL
4513 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4514 \ -- \ ID divided by 1
4515 \ -- \ MC MODE = up to TAxCCRn
4516 \ - \ TACLR clear timer count
4519 \ ----------------------------------\
4520 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4521 \ ----------------------------------\
4523 \ --- \ TAIDEX pre divisor
4524 \ ----------------------------------\
4525 \ %0000 0000 0000 0101 \ TAxCCR0
4526 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4527 \ ----------------------------------\
4528 \ %0000 0000 0001 0000 \ TAxCCTL0
4529 \ - \ CAP capture/compare mode = compare
4532 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4533 \ ----------------------------------\
4535 \ ----------------------------------\
4536 CALL &{RC5TOLCD} \ run previous INIT_HARD_APP
4537 \ ----------------------------------\
4538 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
4539 \ ----------------------------------\
4540 CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
4542 CMP #$0A,TOS \ SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
4543 U>= ?GOTO BW1 \ if yes execute STOP_R2L then RET to BODY of WARM
4545 \ CMP #2,TOS \ Power_ON event
4546 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4547 CMP #4,TOS \ SYSRSTIV|USERSYS RST ?
4548 0= ?GOTO BW1 \ if yes run STOP.
4549 \ CMP #$0E,TOS \ SYSRSTIV = SVSHIFG SVSH event ?
4550 \ 0= ?GOTO BW1 \ SVSHIFG SVSH event performs STOP
4551 \ ----------------------------------\
4553 \ ----------------------------------\
4555 \ ----------------------------------\
4556 #1000 20_US \ 1- wait 20 ms
4557 %011 TOP_LCD \ 2- send DB5=DB4=1
4558 #205 20_US \ 3- wait 4,1 ms
4559 %011 TOP_LCD \ 4- send again DB5=DB4=1
4560 #5 20_US \ 5- wait 0,1 ms
4561 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4562 #2 20_US \ wait 40 us = LCD cycle
4563 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4564 #2 20_US \ wait 40 us = LCD cycle
4565 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4566 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4567 LCD_CLEAR \ 10- "LCD_Clear"
4568 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4569 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4570 LCD_CLEAR \ 10- "LCD_Clear"
4572 MOV @RSP+,PC \ RET to WARM|START
4574 \ ----------------------------------\
4576 \ ----------------------------------\
4577 CODE START \ this routine replaces INT_HARD_APP default values by these of this application.
4578 \ ----------------------------------\
4579 CMP #WDT_INT,&WDT_TIM_0_VEC \ value set by START
4581 MOV @IP+,PC \ does nothing if already initialised
4583 MOV #STOP_R2L,&{RC5TOLCD}-2 \ execution of {RC5TOLCD} will perform STOP_R2L.
4584 KERNEL_ADDON $3C00 TSTBIT \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
4586 MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
4587 MOV #INIT_R2L,&UART_WARM+2 \ replace it by RC5toLCD INI_APP
4589 MOV &I2C_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
4590 MOV #INIT_R2L,&I2C_WARM+2 \ replace it by RC5toLCD INI_APP
4592 MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
4593 MOV #WDT_INT,&WDT_TIM_0_VEC \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4594 MOV &IR_VEC,&{RC5TOLCD}+4 \ save Vector previous value
4595 MOV #RC5_INT,&IR_VEC \ init interrupt vector
4596 \ ----------------------------------\
4597 \ init 20 us count loop \ see 20_US
4598 \ ----------------------------------\ -- TOS
4599 SUB #6,PSP \ -- x x x TOS
4600 MOV TOS,4(PSP) \ -- TOS x x TOS
4601 MOV &FREQ_KHZ,2(PSP) \ -- TOS DVDlo x TOS
4602 MOV #0,0(PSP) \ -- TOS DVDlo DVDhi TOS
4603 MOV #200,TOS \ -- TOS DVDlo DVDhi DIVlo
4604 CALL #MUSMOD \ -- TOS REMlo QUOTlo QUOThi
4605 MOV @PSP,&{RC5TOLCD}+6 \ set count+2 for 20_US
4606 ADD #4,PSP \ -- TOS QUOThi
4607 MOV @PSP+,TOS \ -- TOS
4608 \ ----------------------------------\
4609 CALL #INIT_R2L \ run new INIT_HARD_APP
4611 \ ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4612 \ ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4613 \ CR ." I love you" \ display message on LCD
4614 \ ['] CR >BODY IS CR \ CR executes its default value
4615 \ ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4616 ." RC5toLCD is running," \
4617 ." Type STOP to quit." \ display message on FastForth Terminal
4619 MOV #ABORT,PC \ goto FORTH interpreter without WARM message.
4621 \ ----------------------------------\