1 \ -*- coding: utf-8 -*-
3 ; -----------------------------------
4 ; PROG100k.f = 77 x RC5toLCD.f
5 ; -----------------------------------
8 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
11 \ MY_MSP430FR5738 MY_MSP430FR5738_1 MY_MSP430FR5738_2
12 \ MY_MSP430FR5948 MY_MSP430FR5948_1
15 \ Copyright (C) <2016> <J.M. THOORENS>
17 \ This program is free software: you can redistribute it and/or modify
18 \ it under the terms of the GNU General Public License as published by
19 \ the Free Software Foundation, either version 3 of the License, or
20 \ (at your option) any later version.
22 \ This program is distributed in the hope that it will be useful,
23 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
24 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 \ GNU General Public License for more details.
27 \ You should have received a copy of the GNU General Public License
28 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
31 \ ===========================================================================
32 \ remember: for good downloading to target, all lines must be ended with CR+LF !
33 \ ===========================================================================
37 \ R4 to R7 must be saved before use and restored after
38 \ scratch registers Y to S are free for use
39 \ under interrupt, IP is free for use
40 \ interrupts reset SR register !
42 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
43 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
45 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
47 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
48 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
50 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
52 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
53 \ ASSEMBLER conditionnal usage before ?JMP ?GOTO : S< S>= U< U>= 0= 0<> 0<
55 \ FORTH conditionnal : 0= 0< = < > U<
57 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
58 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
59 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
61 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
62 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
63 \ without usage of an auxiliary 5V to feed the LCD_Vo
64 \ and without potentiometer to adjust the LCD contrast :
65 \ to adjust LCD contrast, just press S1 (-) or S2 (+)
66 \ LCDVo current consumption ~ 500 uA.
68 \ ===================================================================================
69 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
70 \ ===================================================================================
73 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
75 \ GND <-------+---0V0----------> 1 LCD_Vss
76 \ VCC >------ | --3V6-----+----> 2 LCD_Vdd
83 \ LCD_TIM_.2 >---||--+--^/\/\/v--+----> 3 LCD_Vo (= 0V6 without modulation)
84 \ -------------------------> 4 LCD_RW
85 \ -------------------------> 5 LCD_RW
86 \ -------------------------> 6 LCD_EN
87 \ <------------------------> 11 LCD_DB4
88 \ <------------------------> 12 LCD_DB5
89 \ <------------------------> 13 LCD_DB5
90 \ <------------------------> 14 LCD_DB7
92 \ <----- LCD contrast + <--- Sw1 <--- (finger) :-)
93 \ <----- LCD contrast - <--- Sw2 <--- (finger) :-)
95 \ rc5 <--- OUT IR_Receiver (1 TSOP32236)
99 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
103 CODE 20_US \ n -- n * 20 us
104 BEGIN \ here we presume that LCD_TIM_IFG = 1...
106 BIT #1,&LCD_TIM_CTL \ 3
107 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
108 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
110 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
115 CODE TOP_LCD \ LCD Sample
116 \ \ if write : %xxxxWWWW --
117 \ \ if read : -- %0000RRRR
118 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
119 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
120 0= IF \ write LCD bits pattern
122 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
123 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
126 THEN \ read LCD bits pattern
129 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
130 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
135 CODE LCD_WRC \ char -- Write Char
136 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
138 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
139 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
140 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
141 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
142 COLON \ high level word starts here
143 TOP_LCD 2 20_US \ write high nibble first
147 CODE LCD_WRF \ func -- Write Fonction
148 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
152 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
153 : LCD_HOME $02 LCD_WRF 100 20_us ;
155 \ [UNDEFINED] OR [IF]
157 \ \ https://forth-standard.org/standard/core/OR
158 \ \ C OR x1 x2 -- x3 logical OR
166 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
167 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
168 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
169 \ : LCD_FN_SET $20 OR LCD_WrF ;
170 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
171 \ : LCD_GOTO $80 OR LCD_WrF ;
174 \ CODE LCD_RDS \ -- status Read Status
175 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
176 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
177 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
178 \ COLON \ starts a FORTH word
179 \ TOP_LCD 2 20_us \ -- %0000HHHH
180 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
181 \ HI2LO \ switch from FORTH to assembler
182 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
183 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
184 \ MOV @RSP+,IP \ restore IP saved by COLON
188 \ CODE LCD_RDC \ -- char Read Char
189 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
194 \ ******************************\
195 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
196 \ ******************************\
197 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
198 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
199 BIT.B #SW2,&SW2_IN \ test switch S2
200 0= IF \ case of switch S2 pressed
201 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
203 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
206 BIT.B #SW1,&SW1_IN \ test switch S1 input
207 0= IF \ case of Switch S1 pressed
208 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
210 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
214 BW1 \ from quit on truncated RC5 message, repeated RC5 command
218 \ ******************************\
219 ASM RC5_INT \ wake up on Px.RC5 change interrupt
220 \ ******************************\
221 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
222 \ ******************************\
223 \ \ in : SR(9)=old Toggle bit memory (ADD on)
224 \ \ SMclock = 8|16|24 MHz
225 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
226 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
227 \ \ SR(9)=new Toggle bit memory (ADD on)
228 \ ******************************\
229 \ RC5_FirstStartBitHalfCycle: \
230 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
231 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
232 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
233 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
235 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
236 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
238 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
239 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
241 MOV #1778,X \ RC5_Period * 1us
242 MOV #14,W \ count of loop
244 \ ******************************\
245 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
246 \ ******************************\ |
247 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
248 \ RC5_Compute_3/4_Period: \ |
249 RRUM #1,X \ X=1/2 cycle |
252 ADD X,Y \ Y=3/4 cycle
253 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
255 \ ******************************\
256 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
257 \ ******************************\
258 BIT.B #RC5,&IR_IN \ C_flag = IR bit
259 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
260 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
261 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
262 SUB #1,W \ decrement count loop
263 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
264 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
265 0<> WHILE \ ----> out of loop ----+
266 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
268 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
269 CMP Y,X \ 1 | cycle time out of bound ?
271 BIC #$30,&RC5_TIM_CTL \ | | stop timer
272 GOTO BW1 \ | | quit on truncated RC5 message
274 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
276 REPEAT \ ----> loop back --+ | with X = new RC5_period value
277 \ ******************************\ |
278 \ RC5_SampleEndOf: \ <---------------------+
279 \ ******************************\
280 BIC #$30,&RC5_TIM_CTL \ stop timer
281 \ ******************************\
282 \ RC5_ComputeNewRC5word \
283 \ ******************************\
284 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
285 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
286 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
287 \ ******************************\
289 \ ******************************\
290 BIT #BIT14,T \ test /C6 bit in T
291 0= IF BIS #BIT6,X \ set C6 bit in X
292 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
293 \ ******************************\
294 \ RC5_CommandByteIsDone \ -- BASE RC5_code
295 \ ******************************\
296 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
297 \ ******************************\
298 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
299 XOR @RSP,T \ (new XOR old) Toggle bits
300 BIT #UF10,T \ repeated RC5_command ?
301 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
302 XOR #UF10,0(RSP) \ 5 toggle bit memory
303 \ ******************************\
304 \ Display IR_RC5 code \
305 \ ******************************\
306 SUB #8,PSP \ TOS -- x x x x TOS
307 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
308 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
309 MOV #$10,&BASEADR \ set hexadecimal base
310 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
311 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
312 LO2HI \ switch from assembler to FORTH
313 LCD_CLEAR \ set LCD cursor at home
314 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
315 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
316 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
317 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
318 HI2LO \ -- switch from FORTH to assembler
319 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
320 MOV @PSP+,TOS \ -- TOS
324 \ ------------------------------\
326 \ ------------------------------\
328 \ ... \ insert here your background task
331 CALL &RXON \ comment this line to disable TERMINAL
333 \ ******************************\
334 \ here start all interrupts \
335 \ ******************************\
336 \ here return all interrupts \
337 \ ******************************\
341 \ ------------------------------\
342 CODE STOP \ stops multitasking, must to be used before downloading app
343 \ ------------------------------\
344 \ restore default action of primary DEFERred word SLEEP (assembly version)
345 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
346 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
347 MOV X,-2(X) \ restore the default background
348 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
349 ['] WARM >BODY IS WARM \ restore the default WARM
351 ." RC5toLCD is removed. type START to restart"
352 COLD \ performs reset to reset all interrupt vectors.
355 \ ------------------------------\
356 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
357 \ ------------------------------\
358 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
359 \ - - \CNTL Counter lentgh \ 00 = 16 bits
360 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
361 \ -- \ID input divider \ 10 = /4
362 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
363 \ - \TBCLR TimerB Clear
366 \ -------------------------------\
367 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
368 \ -- \CM Capture Mode
373 \ --- \OUTMOD \ 011 = set/reset
379 \ -------------------------------\
381 \ -------------------------------\
383 \ ------------------------------\
384 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
385 \ ------------------------------\
386 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
387 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
388 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
389 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
391 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
392 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
394 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
395 \ ------------------------------\
396 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
397 \ ------------------------------\
398 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
399 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
400 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
401 \ ------------------------------\
402 BIS.B #LCDVo,&LCDVo_DIR \
403 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
404 \ ------------------------------\
405 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
406 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
407 \ ------------------------------\
408 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
409 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
410 \ ******************************\
412 \ ******************************\
413 BIS.B #RC5,&IR_IE \ enable RC5_Int
414 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
415 MOV #RC5_INT,&IR_Vec \ init interrupt vector
416 \ ******************************\
417 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
418 \ ******************************\
419 \ %01 0001 0100 \ TAxCTL
420 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
421 \ -- \ ID divided by 1
422 \ -- \ MC MODE = up to TAxCCRn
423 \ - \ TACLR clear timer count
426 \ ------------------------------\
427 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
428 \ ------------------------------\
430 \ --- \ TAIDEX pre divisor
431 \ ------------------------------\
432 \ %0000 0000 0000 0101 \ TAxCCR0
433 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
434 \ ------------------------------\
435 \ %0000 0000 0001 0000 \ TAxCCTL0
436 \ - \ CAP capture/compare mode = compare
439 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
440 \ ------------------------------\
441 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
442 \ ------------------------------\
443 \ define LPM mode for ACCEPT \
444 \ ------------------------------\
445 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
446 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
447 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
448 \ ------------------------------\
450 \ ------------------------------\
451 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
452 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
453 \ ------------------------------\
454 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
455 \ ------------------------------\
456 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
457 \ CMP #2,Y \ Power_ON event
458 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
460 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
462 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
464 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
466 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
467 \ ------------------------------\
469 \ ------------------------------\
471 \ ------------------------------\
472 #1000 20_US \ 1- wait 20 ms
473 %011 TOP_LCD \ 2- send DB5=DB4=1
474 #205 20_US \ 3- wait 4,1 ms
475 %011 TOP_LCD \ 4- send again DB5=DB4=1
476 #5 20_US \ 5- wait 0,1 ms
477 %011 TOP_LCD \ 6- send again again DB5=DB4=1
478 #2 20_US \ wait 40 us = LCD cycle
479 %010 TOP_LCD \ 7- send DB5=1 DB4=0
480 #2 20_US \ wait 40 us = LCD cycle
481 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
482 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
483 LCD_CLEAR \ 10- "LCD_Clear"
484 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
485 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
486 LCD_CLEAR \ 10- "LCD_Clear"
487 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
488 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
489 CR ." I love you" \ display message on LCD
490 ['] CR >BODY IS CR \ CR executes its default value
491 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
492 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
493 ABORT \ ...and end APP_INIT with ABORT, no return.
496 \ ------------------------------\
497 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
498 \ ------------------------------\
499 MOV #SLEEP,X \ replace default background process
500 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
501 MOV #WARM,X \ replace default WARM
502 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
503 MOV X,PC \ then execute it
506 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
510 CODE 20_US \ n -- n * 20 us
511 BEGIN \ here we presume that LCD_TIM_IFG = 1...
513 BIT #1,&LCD_TIM_CTL \ 3
514 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
515 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
517 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
522 CODE TOP_LCD \ LCD Sample
523 \ \ if write : %xxxxWWWW --
524 \ \ if read : -- %0000RRRR
525 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
526 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
527 0= IF \ write LCD bits pattern
529 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
530 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
533 THEN \ read LCD bits pattern
536 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
537 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
542 CODE LCD_WRC \ char -- Write Char
543 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
545 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
546 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
547 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
548 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
549 COLON \ high level word starts here
550 TOP_LCD 2 20_US \ write high nibble first
554 CODE LCD_WRF \ func -- Write Fonction
555 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
559 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
560 : LCD_HOME $02 LCD_WRF 100 20_us ;
562 \ [UNDEFINED] OR [IF]
564 \ \ https://forth-standard.org/standard/core/OR
565 \ \ C OR x1 x2 -- x3 logical OR
573 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
574 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
575 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
576 \ : LCD_FN_SET $20 OR LCD_WrF ;
577 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
578 \ : LCD_GOTO $80 OR LCD_WrF ;
581 \ CODE LCD_RDS \ -- status Read Status
582 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
583 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
584 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
585 \ COLON \ starts a FORTH word
586 \ TOP_LCD 2 20_us \ -- %0000HHHH
587 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
588 \ HI2LO \ switch from FORTH to assembler
589 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
590 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
591 \ MOV @RSP+,IP \ restore IP saved by COLON
595 \ CODE LCD_RDC \ -- char Read Char
596 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
601 \ ******************************\
602 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
603 \ ******************************\
604 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
605 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
606 BIT.B #SW2,&SW2_IN \ test switch S2
607 0= IF \ case of switch S2 pressed
608 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
610 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
613 BIT.B #SW1,&SW1_IN \ test switch S1 input
614 0= IF \ case of Switch S1 pressed
615 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
617 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
621 BW1 \ from quit on truncated RC5 message, repeated RC5 command
625 \ ******************************\
626 ASM RC5_INT \ wake up on Px.RC5 change interrupt
627 \ ******************************\
628 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
629 \ ******************************\
630 \ \ in : SR(9)=old Toggle bit memory (ADD on)
631 \ \ SMclock = 8|16|24 MHz
632 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
633 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
634 \ \ SR(9)=new Toggle bit memory (ADD on)
635 \ ******************************\
636 \ RC5_FirstStartBitHalfCycle: \
637 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
638 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
639 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
640 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
642 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
643 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
645 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
646 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
648 MOV #1778,X \ RC5_Period * 1us
649 MOV #14,W \ count of loop
651 \ ******************************\
652 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
653 \ ******************************\ |
654 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
655 \ RC5_Compute_3/4_Period: \ |
656 RRUM #1,X \ X=1/2 cycle |
659 ADD X,Y \ Y=3/4 cycle
660 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
662 \ ******************************\
663 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
664 \ ******************************\
665 BIT.B #RC5,&IR_IN \ C_flag = IR bit
666 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
667 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
668 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
669 SUB #1,W \ decrement count loop
670 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
671 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
672 0<> WHILE \ ----> out of loop ----+
673 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
675 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
676 CMP Y,X \ 1 | cycle time out of bound ?
678 BIC #$30,&RC5_TIM_CTL \ | | stop timer
679 GOTO BW1 \ | | quit on truncated RC5 message
681 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
683 REPEAT \ ----> loop back --+ | with X = new RC5_period value
684 \ ******************************\ |
685 \ RC5_SampleEndOf: \ <---------------------+
686 \ ******************************\
687 BIC #$30,&RC5_TIM_CTL \ stop timer
688 \ ******************************\
689 \ RC5_ComputeNewRC5word \
690 \ ******************************\
691 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
692 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
693 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
694 \ ******************************\
696 \ ******************************\
697 BIT #BIT14,T \ test /C6 bit in T
698 0= IF BIS #BIT6,X \ set C6 bit in X
699 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
700 \ ******************************\
701 \ RC5_CommandByteIsDone \ -- BASE RC5_code
702 \ ******************************\
703 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
704 \ ******************************\
705 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
706 XOR @RSP,T \ (new XOR old) Toggle bits
707 BIT #UF10,T \ repeated RC5_command ?
708 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
709 XOR #UF10,0(RSP) \ 5 toggle bit memory
710 \ ******************************\
711 \ Display IR_RC5 code \
712 \ ******************************\
713 SUB #8,PSP \ TOS -- x x x x TOS
714 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
715 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
716 MOV #$10,&BASEADR \ set hexadecimal base
717 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
718 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
719 LO2HI \ switch from assembler to FORTH
720 LCD_CLEAR \ set LCD cursor at home
721 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
722 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
723 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
724 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
725 HI2LO \ -- switch from FORTH to assembler
726 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
727 MOV @PSP+,TOS \ -- TOS
731 \ ------------------------------\
733 \ ------------------------------\
735 \ ... \ insert here your background task
738 CALL &RXON \ comment this line to disable TERMINAL
740 \ ******************************\
741 \ here start all interrupts \
742 \ ******************************\
743 \ here return all interrupts \
744 \ ******************************\
748 \ ------------------------------\
749 CODE STOP \ stops multitasking, must to be used before downloading app
750 \ ------------------------------\
751 \ restore default action of primary DEFERred word SLEEP (assembly version)
752 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
753 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
754 MOV X,-2(X) \ restore the default background
755 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
756 ['] WARM >BODY IS WARM \ restore the default WARM
758 ." RC5toLCD is removed. type START to restart"
759 COLD \ performs reset to reset all interrupt vectors.
762 \ ------------------------------\
763 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
764 \ ------------------------------\
765 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
766 \ - - \CNTL Counter lentgh \ 00 = 16 bits
767 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
768 \ -- \ID input divider \ 10 = /4
769 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
770 \ - \TBCLR TimerB Clear
773 \ -------------------------------\
774 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
775 \ -- \CM Capture Mode
780 \ --- \OUTMOD \ 011 = set/reset
786 \ -------------------------------\
788 \ -------------------------------\
790 \ ------------------------------\
791 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
792 \ ------------------------------\
793 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
794 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
795 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
796 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
798 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
799 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
801 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
802 \ ------------------------------\
803 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
804 \ ------------------------------\
805 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
806 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
807 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
808 \ ------------------------------\
809 BIS.B #LCDVo,&LCDVo_DIR \
810 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
811 \ ------------------------------\
812 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
813 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
814 \ ------------------------------\
815 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
816 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
817 \ ******************************\
819 \ ******************************\
820 BIS.B #RC5,&IR_IE \ enable RC5_Int
821 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
822 MOV #RC5_INT,&IR_Vec \ init interrupt vector
823 \ ******************************\
824 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
825 \ ******************************\
826 \ %01 0001 0100 \ TAxCTL
827 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
828 \ -- \ ID divided by 1
829 \ -- \ MC MODE = up to TAxCCRn
830 \ - \ TACLR clear timer count
833 \ ------------------------------\
834 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
835 \ ------------------------------\
837 \ --- \ TAIDEX pre divisor
838 \ ------------------------------\
839 \ %0000 0000 0000 0101 \ TAxCCR0
840 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
841 \ ------------------------------\
842 \ %0000 0000 0001 0000 \ TAxCCTL0
843 \ - \ CAP capture/compare mode = compare
846 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
847 \ ------------------------------\
848 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
849 \ ------------------------------\
850 \ define LPM mode for ACCEPT \
851 \ ------------------------------\
852 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
853 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
854 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
855 \ ------------------------------\
857 \ ------------------------------\
858 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
859 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
860 \ ------------------------------\
861 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
862 \ ------------------------------\
863 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
864 \ CMP #2,Y \ Power_ON event
865 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
867 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
869 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
871 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
873 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
874 \ ------------------------------\
876 \ ------------------------------\
878 \ ------------------------------\
879 #1000 20_US \ 1- wait 20 ms
880 %011 TOP_LCD \ 2- send DB5=DB4=1
881 #205 20_US \ 3- wait 4,1 ms
882 %011 TOP_LCD \ 4- send again DB5=DB4=1
883 #5 20_US \ 5- wait 0,1 ms
884 %011 TOP_LCD \ 6- send again again DB5=DB4=1
885 #2 20_US \ wait 40 us = LCD cycle
886 %010 TOP_LCD \ 7- send DB5=1 DB4=0
887 #2 20_US \ wait 40 us = LCD cycle
888 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
889 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
890 LCD_CLEAR \ 10- "LCD_Clear"
891 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
892 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
893 LCD_CLEAR \ 10- "LCD_Clear"
894 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
895 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
896 CR ." I love you" \ display message on LCD
897 ['] CR >BODY IS CR \ CR executes its default value
898 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
899 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
900 ABORT \ ...and end APP_INIT with ABORT, no return.
903 \ ------------------------------\
904 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
905 \ ------------------------------\
906 MOV #SLEEP,X \ replace default background process
907 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
908 MOV #WARM,X \ replace default WARM
909 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
910 MOV X,PC \ then execute it
913 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
917 CODE 20_US \ n -- n * 20 us
918 BEGIN \ here we presume that LCD_TIM_IFG = 1...
920 BIT #1,&LCD_TIM_CTL \ 3
921 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
922 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
924 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
929 CODE TOP_LCD \ LCD Sample
930 \ \ if write : %xxxxWWWW --
931 \ \ if read : -- %0000RRRR
932 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
933 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
934 0= IF \ write LCD bits pattern
936 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
937 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
940 THEN \ read LCD bits pattern
943 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
944 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
949 CODE LCD_WRC \ char -- Write Char
950 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
952 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
953 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
954 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
955 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
956 COLON \ high level word starts here
957 TOP_LCD 2 20_US \ write high nibble first
961 CODE LCD_WRF \ func -- Write Fonction
962 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
966 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
967 : LCD_HOME $02 LCD_WRF 100 20_us ;
969 \ [UNDEFINED] OR [IF]
971 \ \ https://forth-standard.org/standard/core/OR
972 \ \ C OR x1 x2 -- x3 logical OR
980 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
981 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
982 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
983 \ : LCD_FN_SET $20 OR LCD_WrF ;
984 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
985 \ : LCD_GOTO $80 OR LCD_WrF ;
988 \ CODE LCD_RDS \ -- status Read Status
989 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
990 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
991 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
992 \ COLON \ starts a FORTH word
993 \ TOP_LCD 2 20_us \ -- %0000HHHH
994 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
995 \ HI2LO \ switch from FORTH to assembler
996 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
997 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
998 \ MOV @RSP+,IP \ restore IP saved by COLON
1002 \ CODE LCD_RDC \ -- char Read Char
1003 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1008 \ ******************************\
1009 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1010 \ ******************************\
1011 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1012 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1013 BIT.B #SW2,&SW2_IN \ test switch S2
1014 0= IF \ case of switch S2 pressed
1015 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1017 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1020 BIT.B #SW1,&SW1_IN \ test switch S1 input
1021 0= IF \ case of Switch S1 pressed
1022 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1024 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1028 BW1 \ from quit on truncated RC5 message, repeated RC5 command
1032 \ ******************************\
1033 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1034 \ ******************************\
1035 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1036 \ ******************************\
1037 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1038 \ \ SMclock = 8|16|24 MHz
1039 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1040 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1041 \ \ SR(9)=new Toggle bit memory (ADD on)
1042 \ ******************************\
1043 \ RC5_FirstStartBitHalfCycle: \
1044 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1045 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1046 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1047 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1049 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1050 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1052 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
1053 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1055 MOV #1778,X \ RC5_Period * 1us
1056 MOV #14,W \ count of loop
1058 \ ******************************\
1059 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1060 \ ******************************\ |
1061 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1062 \ RC5_Compute_3/4_Period: \ |
1063 RRUM #1,X \ X=1/2 cycle |
1066 ADD X,Y \ Y=3/4 cycle
1067 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1069 \ ******************************\
1070 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1071 \ ******************************\
1072 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1073 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1074 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1075 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1076 SUB #1,W \ decrement count loop
1077 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1078 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1079 0<> WHILE \ ----> out of loop ----+
1080 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1082 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1083 CMP Y,X \ 1 | cycle time out of bound ?
1085 BIC #$30,&RC5_TIM_CTL \ | | stop timer
1086 GOTO BW1 \ | | quit on truncated RC5 message
1088 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1090 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1091 \ ******************************\ |
1092 \ RC5_SampleEndOf: \ <---------------------+
1093 \ ******************************\
1094 BIC #$30,&RC5_TIM_CTL \ stop timer
1095 \ ******************************\
1096 \ RC5_ComputeNewRC5word \
1097 \ ******************************\
1098 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1099 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1100 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1101 \ ******************************\
1102 \ RC5_ComputeC6bit \
1103 \ ******************************\
1104 BIT #BIT14,T \ test /C6 bit in T
1105 0= IF BIS #BIT6,X \ set C6 bit in X
1106 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1107 \ ******************************\
1108 \ RC5_CommandByteIsDone \ -- BASE RC5_code
1109 \ ******************************\
1110 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1111 \ ******************************\
1112 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1113 XOR @RSP,T \ (new XOR old) Toggle bits
1114 BIT #UF10,T \ repeated RC5_command ?
1115 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
1116 XOR #UF10,0(RSP) \ 5 toggle bit memory
1117 \ ******************************\
1118 \ Display IR_RC5 code \
1119 \ ******************************\
1120 SUB #8,PSP \ TOS -- x x x x TOS
1121 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
1122 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
1123 MOV #$10,&BASEADR \ set hexadecimal base
1124 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
1125 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
1126 LO2HI \ switch from assembler to FORTH
1127 LCD_CLEAR \ set LCD cursor at home
1128 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
1129 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1130 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
1131 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
1132 HI2LO \ -- switch from FORTH to assembler
1133 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
1134 MOV @PSP+,TOS \ -- TOS
1138 \ ------------------------------\
1140 \ ------------------------------\
1142 \ ... \ insert here your background task
1145 CALL &RXON \ comment this line to disable TERMINAL
1147 \ ******************************\
1148 \ here start all interrupts \
1149 \ ******************************\
1150 \ here return all interrupts \
1151 \ ******************************\
1155 \ ------------------------------\
1156 CODE STOP \ stops multitasking, must to be used before downloading app
1157 \ ------------------------------\
1158 \ restore default action of primary DEFERred word SLEEP (assembly version)
1159 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
1160 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1161 MOV X,-2(X) \ restore the default background
1162 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1163 ['] WARM >BODY IS WARM \ restore the default WARM
1165 ." RC5toLCD is removed. type START to restart"
1166 COLD \ performs reset to reset all interrupt vectors.
1169 \ ------------------------------\
1170 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
1171 \ ------------------------------\
1172 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1173 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1174 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1175 \ -- \ID input divider \ 10 = /4
1176 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1177 \ - \TBCLR TimerB Clear
1180 \ -------------------------------\
1181 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1182 \ -- \CM Capture Mode
1187 \ --- \OUTMOD \ 011 = set/reset
1193 \ -------------------------------\
1195 \ -------------------------------\
1197 \ ------------------------------\
1198 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1199 \ ------------------------------\
1200 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1201 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1202 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
1203 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1205 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
1206 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1208 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1209 \ ------------------------------\
1210 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1211 \ ------------------------------\
1212 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1213 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1214 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1215 \ ------------------------------\
1216 BIS.B #LCDVo,&LCDVo_DIR \
1217 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1218 \ ------------------------------\
1219 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1220 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1221 \ ------------------------------\
1222 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1223 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1224 \ ******************************\
1226 \ ******************************\
1227 BIS.B #RC5,&IR_IE \ enable RC5_Int
1228 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1229 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1230 \ ******************************\
1231 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1232 \ ******************************\
1233 \ %01 0001 0100 \ TAxCTL
1234 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1235 \ -- \ ID divided by 1
1236 \ -- \ MC MODE = up to TAxCCRn
1237 \ - \ TACLR clear timer count
1240 \ ------------------------------\
1241 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1242 \ ------------------------------\
1244 \ --- \ TAIDEX pre divisor
1245 \ ------------------------------\
1246 \ %0000 0000 0000 0101 \ TAxCCR0
1247 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1248 \ ------------------------------\
1249 \ %0000 0000 0001 0000 \ TAxCCTL0
1250 \ - \ CAP capture/compare mode = compare
1253 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1254 \ ------------------------------\
1255 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1256 \ ------------------------------\
1257 \ define LPM mode for ACCEPT \
1258 \ ------------------------------\
1259 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1260 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1261 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1262 \ ------------------------------\
1264 \ ------------------------------\
1265 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
1266 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
1267 \ ------------------------------\
1268 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
1269 \ ------------------------------\
1270 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
1271 \ CMP #2,Y \ Power_ON event
1272 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1274 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
1276 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
1278 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
1280 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
1281 \ ------------------------------\
1283 \ ------------------------------\
1285 \ ------------------------------\
1286 #1000 20_US \ 1- wait 20 ms
1287 %011 TOP_LCD \ 2- send DB5=DB4=1
1288 #205 20_US \ 3- wait 4,1 ms
1289 %011 TOP_LCD \ 4- send again DB5=DB4=1
1290 #5 20_US \ 5- wait 0,1 ms
1291 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1292 #2 20_US \ wait 40 us = LCD cycle
1293 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1294 #2 20_US \ wait 40 us = LCD cycle
1295 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1296 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1297 LCD_CLEAR \ 10- "LCD_Clear"
1298 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1299 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1300 LCD_CLEAR \ 10- "LCD_Clear"
1301 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1302 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1303 CR ." I love you" \ display message on LCD
1304 ['] CR >BODY IS CR \ CR executes its default value
1305 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1306 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1307 ABORT \ ...and end APP_INIT with ABORT, no return.
1310 \ ------------------------------\
1311 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
1312 \ ------------------------------\
1313 MOV #SLEEP,X \ replace default background process
1314 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
1315 MOV #WARM,X \ replace default WARM
1316 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
1317 MOV X,PC \ then execute it
1320 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
1324 CODE 20_US \ n -- n * 20 us
1325 BEGIN \ here we presume that LCD_TIM_IFG = 1...
1327 BIT #1,&LCD_TIM_CTL \ 3
1328 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
1329 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
1331 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
1336 CODE TOP_LCD \ LCD Sample
1337 \ \ if write : %xxxxWWWW --
1338 \ \ if read : -- %0000RRRR
1339 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1340 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1341 0= IF \ write LCD bits pattern
1343 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1344 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1347 THEN \ read LCD bits pattern
1350 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1351 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1356 CODE LCD_WRC \ char -- Write Char
1357 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1359 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1360 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1361 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1362 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1363 COLON \ high level word starts here
1364 TOP_LCD 2 20_US \ write high nibble first
1368 CODE LCD_WRF \ func -- Write Fonction
1369 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1373 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1374 : LCD_HOME $02 LCD_WRF 100 20_us ;
1376 \ [UNDEFINED] OR [IF]
1378 \ \ https://forth-standard.org/standard/core/OR
1379 \ \ C OR x1 x2 -- x3 logical OR
1387 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
1388 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
1389 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
1390 \ : LCD_FN_SET $20 OR LCD_WrF ;
1391 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
1392 \ : LCD_GOTO $80 OR LCD_WrF ;
1395 \ CODE LCD_RDS \ -- status Read Status
1396 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1397 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1398 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1399 \ COLON \ starts a FORTH word
1400 \ TOP_LCD 2 20_us \ -- %0000HHHH
1401 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1402 \ HI2LO \ switch from FORTH to assembler
1403 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1404 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1405 \ MOV @RSP+,IP \ restore IP saved by COLON
1409 \ CODE LCD_RDC \ -- char Read Char
1410 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1415 \ ******************************\
1416 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1417 \ ******************************\
1418 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1419 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1420 BIT.B #SW2,&SW2_IN \ test switch S2
1421 0= IF \ case of switch S2 pressed
1422 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1424 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1427 BIT.B #SW1,&SW1_IN \ test switch S1 input
1428 0= IF \ case of Switch S1 pressed
1429 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1431 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1435 BW1 \ from quit on truncated RC5 message, repeated RC5 command
1439 \ ******************************\
1440 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1441 \ ******************************\
1442 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1443 \ ******************************\
1444 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1445 \ \ SMclock = 8|16|24 MHz
1446 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1447 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1448 \ \ SR(9)=new Toggle bit memory (ADD on)
1449 \ ******************************\
1450 \ RC5_FirstStartBitHalfCycle: \
1451 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1452 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1453 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1454 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1456 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1457 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1459 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
1460 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1462 MOV #1778,X \ RC5_Period * 1us
1463 MOV #14,W \ count of loop
1465 \ ******************************\
1466 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1467 \ ******************************\ |
1468 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1469 \ RC5_Compute_3/4_Period: \ |
1470 RRUM #1,X \ X=1/2 cycle |
1473 ADD X,Y \ Y=3/4 cycle
1474 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1476 \ ******************************\
1477 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1478 \ ******************************\
1479 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1480 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1481 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1482 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1483 SUB #1,W \ decrement count loop
1484 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1485 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1486 0<> WHILE \ ----> out of loop ----+
1487 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1489 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1490 CMP Y,X \ 1 | cycle time out of bound ?
1492 BIC #$30,&RC5_TIM_CTL \ | | stop timer
1493 GOTO BW1 \ | | quit on truncated RC5 message
1495 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1497 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1498 \ ******************************\ |
1499 \ RC5_SampleEndOf: \ <---------------------+
1500 \ ******************************\
1501 BIC #$30,&RC5_TIM_CTL \ stop timer
1502 \ ******************************\
1503 \ RC5_ComputeNewRC5word \
1504 \ ******************************\
1505 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1506 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1507 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1508 \ ******************************\
1509 \ RC5_ComputeC6bit \
1510 \ ******************************\
1511 BIT #BIT14,T \ test /C6 bit in T
1512 0= IF BIS #BIT6,X \ set C6 bit in X
1513 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1514 \ ******************************\
1515 \ RC5_CommandByteIsDone \ -- BASE RC5_code
1516 \ ******************************\
1517 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1518 \ ******************************\
1519 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1520 XOR @RSP,T \ (new XOR old) Toggle bits
1521 BIT #UF10,T \ repeated RC5_command ?
1522 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
1523 XOR #UF10,0(RSP) \ 5 toggle bit memory
1524 \ ******************************\
1525 \ Display IR_RC5 code \
1526 \ ******************************\
1527 SUB #8,PSP \ TOS -- x x x x TOS
1528 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
1529 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
1530 MOV #$10,&BASEADR \ set hexadecimal base
1531 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
1532 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
1533 LO2HI \ switch from assembler to FORTH
1534 LCD_CLEAR \ set LCD cursor at home
1535 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
1536 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1537 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
1538 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
1539 HI2LO \ -- switch from FORTH to assembler
1540 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
1541 MOV @PSP+,TOS \ -- TOS
1545 \ ------------------------------\
1547 \ ------------------------------\
1549 \ ... \ insert here your background task
1552 CALL &RXON \ comment this line to disable TERMINAL
1554 \ ******************************\
1555 \ here start all interrupts \
1556 \ ******************************\
1557 \ here return all interrupts \
1558 \ ******************************\
1562 \ ------------------------------\
1563 CODE STOP \ stops multitasking, must to be used before downloading app
1564 \ ------------------------------\
1565 \ restore default action of primary DEFERred word SLEEP (assembly version)
1566 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
1567 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1568 MOV X,-2(X) \ restore the default background
1569 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1570 ['] WARM >BODY IS WARM \ restore the default WARM
1572 ." RC5toLCD is removed. type START to restart"
1573 COLD \ performs reset to reset all interrupt vectors.
1576 \ ------------------------------\
1577 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
1578 \ ------------------------------\
1579 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1580 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1581 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1582 \ -- \ID input divider \ 10 = /4
1583 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1584 \ - \TBCLR TimerB Clear
1587 \ -------------------------------\
1588 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1589 \ -- \CM Capture Mode
1594 \ --- \OUTMOD \ 011 = set/reset
1600 \ -------------------------------\
1602 \ -------------------------------\
1604 \ ------------------------------\
1605 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1606 \ ------------------------------\
1607 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1608 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1609 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
1610 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1612 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
1613 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1615 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1616 \ ------------------------------\
1617 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1618 \ ------------------------------\
1619 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1620 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1621 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1622 \ ------------------------------\
1623 BIS.B #LCDVo,&LCDVo_DIR \
1624 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1625 \ ------------------------------\
1626 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1627 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1628 \ ------------------------------\
1629 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1630 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1631 \ ******************************\
1633 \ ******************************\
1634 BIS.B #RC5,&IR_IE \ enable RC5_Int
1635 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1636 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1637 \ ******************************\
1638 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1639 \ ******************************\
1640 \ %01 0001 0100 \ TAxCTL
1641 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1642 \ -- \ ID divided by 1
1643 \ -- \ MC MODE = up to TAxCCRn
1644 \ - \ TACLR clear timer count
1647 \ ------------------------------\
1648 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1649 \ ------------------------------\
1651 \ --- \ TAIDEX pre divisor
1652 \ ------------------------------\
1653 \ %0000 0000 0000 0101 \ TAxCCR0
1654 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1655 \ ------------------------------\
1656 \ %0000 0000 0001 0000 \ TAxCCTL0
1657 \ - \ CAP capture/compare mode = compare
1660 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1661 \ ------------------------------\
1662 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1663 \ ------------------------------\
1664 \ define LPM mode for ACCEPT \
1665 \ ------------------------------\
1666 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1667 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1668 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1669 \ ------------------------------\
1671 \ ------------------------------\
1672 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
1673 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
1674 \ ------------------------------\
1675 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
1676 \ ------------------------------\
1677 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
1678 \ CMP #2,Y \ Power_ON event
1679 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1681 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
1683 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
1685 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
1687 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
1688 \ ------------------------------\
1690 \ ------------------------------\
1692 \ ------------------------------\
1693 #1000 20_US \ 1- wait 20 ms
1694 %011 TOP_LCD \ 2- send DB5=DB4=1
1695 #205 20_US \ 3- wait 4,1 ms
1696 %011 TOP_LCD \ 4- send again DB5=DB4=1
1697 #5 20_US \ 5- wait 0,1 ms
1698 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1699 #2 20_US \ wait 40 us = LCD cycle
1700 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1701 #2 20_US \ wait 40 us = LCD cycle
1702 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1703 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1704 LCD_CLEAR \ 10- "LCD_Clear"
1705 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1706 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1707 LCD_CLEAR \ 10- "LCD_Clear"
1708 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1709 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1710 CR ." I love you" \ display message on LCD
1711 ['] CR >BODY IS CR \ CR executes its default value
1712 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1713 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1714 ABORT \ ...and end APP_INIT with ABORT, no return.
1717 \ ------------------------------\
1718 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
1719 \ ------------------------------\
1720 MOV #SLEEP,X \ replace default background process
1721 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
1722 MOV #WARM,X \ replace default WARM
1723 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
1724 MOV X,PC \ then execute it
1727 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
1731 CODE 20_US \ n -- n * 20 us
1732 BEGIN \ here we presume that LCD_TIM_IFG = 1...
1734 BIT #1,&LCD_TIM_CTL \ 3
1735 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
1736 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
1738 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
1743 CODE TOP_LCD \ LCD Sample
1744 \ \ if write : %xxxxWWWW --
1745 \ \ if read : -- %0000RRRR
1746 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1747 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1748 0= IF \ write LCD bits pattern
1750 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1751 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1754 THEN \ read LCD bits pattern
1757 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1758 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1763 CODE LCD_WRC \ char -- Write Char
1764 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1766 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1767 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1768 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1769 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1770 COLON \ high level word starts here
1771 TOP_LCD 2 20_US \ write high nibble first
1775 CODE LCD_WRF \ func -- Write Fonction
1776 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1780 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1781 : LCD_HOME $02 LCD_WRF 100 20_us ;
1783 \ [UNDEFINED] OR [IF]
1785 \ \ https://forth-standard.org/standard/core/OR
1786 \ \ C OR x1 x2 -- x3 logical OR
1794 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
1795 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
1796 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
1797 \ : LCD_FN_SET $20 OR LCD_WrF ;
1798 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
1799 \ : LCD_GOTO $80 OR LCD_WrF ;
1802 \ CODE LCD_RDS \ -- status Read Status
1803 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1804 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1805 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1806 \ COLON \ starts a FORTH word
1807 \ TOP_LCD 2 20_us \ -- %0000HHHH
1808 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1809 \ HI2LO \ switch from FORTH to assembler
1810 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1811 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1812 \ MOV @RSP+,IP \ restore IP saved by COLON
1816 \ CODE LCD_RDC \ -- char Read Char
1817 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1822 \ ******************************\
1823 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1824 \ ******************************\
1825 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1826 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1827 BIT.B #SW2,&SW2_IN \ test switch S2
1828 0= IF \ case of switch S2 pressed
1829 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1831 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1834 BIT.B #SW1,&SW1_IN \ test switch S1 input
1835 0= IF \ case of Switch S1 pressed
1836 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1838 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1842 BW1 \ from quit on truncated RC5 message, repeated RC5 command
1846 \ ******************************\
1847 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1848 \ ******************************\
1849 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1850 \ ******************************\
1851 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1852 \ \ SMclock = 8|16|24 MHz
1853 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1854 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1855 \ \ SR(9)=new Toggle bit memory (ADD on)
1856 \ ******************************\
1857 \ RC5_FirstStartBitHalfCycle: \
1858 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1859 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1860 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1861 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1863 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1864 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1866 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
1867 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1869 MOV #1778,X \ RC5_Period * 1us
1870 MOV #14,W \ count of loop
1872 \ ******************************\
1873 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1874 \ ******************************\ |
1875 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1876 \ RC5_Compute_3/4_Period: \ |
1877 RRUM #1,X \ X=1/2 cycle |
1880 ADD X,Y \ Y=3/4 cycle
1881 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1883 \ ******************************\
1884 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1885 \ ******************************\
1886 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1887 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1888 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1889 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1890 SUB #1,W \ decrement count loop
1891 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1892 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1893 0<> WHILE \ ----> out of loop ----+
1894 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1896 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1897 CMP Y,X \ 1 | cycle time out of bound ?
1899 BIC #$30,&RC5_TIM_CTL \ | | stop timer
1900 GOTO BW1 \ | | quit on truncated RC5 message
1902 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1904 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1905 \ ******************************\ |
1906 \ RC5_SampleEndOf: \ <---------------------+
1907 \ ******************************\
1908 BIC #$30,&RC5_TIM_CTL \ stop timer
1909 \ ******************************\
1910 \ RC5_ComputeNewRC5word \
1911 \ ******************************\
1912 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1913 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1914 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1915 \ ******************************\
1916 \ RC5_ComputeC6bit \
1917 \ ******************************\
1918 BIT #BIT14,T \ test /C6 bit in T
1919 0= IF BIS #BIT6,X \ set C6 bit in X
1920 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1921 \ ******************************\
1922 \ RC5_CommandByteIsDone \ -- BASE RC5_code
1923 \ ******************************\
1924 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1925 \ ******************************\
1926 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1927 XOR @RSP,T \ (new XOR old) Toggle bits
1928 BIT #UF10,T \ repeated RC5_command ?
1929 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
1930 XOR #UF10,0(RSP) \ 5 toggle bit memory
1931 \ ******************************\
1932 \ Display IR_RC5 code \
1933 \ ******************************\
1934 SUB #8,PSP \ TOS -- x x x x TOS
1935 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
1936 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
1937 MOV #$10,&BASEADR \ set hexadecimal base
1938 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
1939 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
1940 LO2HI \ switch from assembler to FORTH
1941 LCD_CLEAR \ set LCD cursor at home
1942 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
1943 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1944 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
1945 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
1946 HI2LO \ -- switch from FORTH to assembler
1947 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
1948 MOV @PSP+,TOS \ -- TOS
1952 \ ------------------------------\
1954 \ ------------------------------\
1956 \ ... \ insert here your background task
1959 CALL &RXON \ comment this line to disable TERMINAL
1961 \ ******************************\
1962 \ here start all interrupts \
1963 \ ******************************\
1964 \ here return all interrupts \
1965 \ ******************************\
1969 \ ------------------------------\
1970 CODE STOP \ stops multitasking, must to be used before downloading app
1971 \ ------------------------------\
1972 \ restore default action of primary DEFERred word SLEEP (assembly version)
1973 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
1974 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1975 MOV X,-2(X) \ restore the default background
1976 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1977 ['] WARM >BODY IS WARM \ restore the default WARM
1979 ." RC5toLCD is removed. type START to restart"
1980 COLD \ performs reset to reset all interrupt vectors.
1983 \ ------------------------------\
1984 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
1985 \ ------------------------------\
1986 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1987 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1988 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1989 \ -- \ID input divider \ 10 = /4
1990 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1991 \ - \TBCLR TimerB Clear
1994 \ -------------------------------\
1995 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1996 \ -- \CM Capture Mode
2001 \ --- \OUTMOD \ 011 = set/reset
2007 \ -------------------------------\
2009 \ -------------------------------\
2011 \ ------------------------------\
2012 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2013 \ ------------------------------\
2014 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2015 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2016 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
2017 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2019 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
2020 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2022 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2023 \ ------------------------------\
2024 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2025 \ ------------------------------\
2026 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2027 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2028 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2029 \ ------------------------------\
2030 BIS.B #LCDVo,&LCDVo_DIR \
2031 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2032 \ ------------------------------\
2033 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2034 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2035 \ ------------------------------\
2036 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2037 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2038 \ ******************************\
2040 \ ******************************\
2041 BIS.B #RC5,&IR_IE \ enable RC5_Int
2042 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2043 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2044 \ ******************************\
2045 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2046 \ ******************************\
2047 \ %01 0001 0100 \ TAxCTL
2048 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2049 \ -- \ ID divided by 1
2050 \ -- \ MC MODE = up to TAxCCRn
2051 \ - \ TACLR clear timer count
2054 \ ------------------------------\
2055 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2056 \ ------------------------------\
2058 \ --- \ TAIDEX pre divisor
2059 \ ------------------------------\
2060 \ %0000 0000 0000 0101 \ TAxCCR0
2061 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2062 \ ------------------------------\
2063 \ %0000 0000 0001 0000 \ TAxCCTL0
2064 \ - \ CAP capture/compare mode = compare
2067 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2068 \ ------------------------------\
2069 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2070 \ ------------------------------\
2071 \ define LPM mode for ACCEPT \
2072 \ ------------------------------\
2073 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2074 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2075 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2076 \ ------------------------------\
2078 \ ------------------------------\
2079 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
2080 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
2081 \ ------------------------------\
2082 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
2083 \ ------------------------------\
2084 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
2085 \ CMP #2,Y \ Power_ON event
2086 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2088 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
2090 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
2092 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
2094 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
2095 \ ------------------------------\
2097 \ ------------------------------\
2099 \ ------------------------------\
2100 #1000 20_US \ 1- wait 20 ms
2101 %011 TOP_LCD \ 2- send DB5=DB4=1
2102 #205 20_US \ 3- wait 4,1 ms
2103 %011 TOP_LCD \ 4- send again DB5=DB4=1
2104 #5 20_US \ 5- wait 0,1 ms
2105 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2106 #2 20_US \ wait 40 us = LCD cycle
2107 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2108 #2 20_US \ wait 40 us = LCD cycle
2109 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2110 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2111 LCD_CLEAR \ 10- "LCD_Clear"
2112 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2113 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2114 LCD_CLEAR \ 10- "LCD_Clear"
2115 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2116 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2117 CR ." I love you" \ display message on LCD
2118 ['] CR >BODY IS CR \ CR executes its default value
2119 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2120 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2121 ABORT \ ...and end APP_INIT with ABORT, no return.
2124 \ ------------------------------\
2125 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
2126 \ ------------------------------\
2127 MOV #SLEEP,X \ replace default background process
2128 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
2129 MOV #WARM,X \ replace default WARM
2130 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
2131 MOV X,PC \ then execute it
2134 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
2138 CODE 20_US \ n -- n * 20 us
2139 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2141 BIT #1,&LCD_TIM_CTL \ 3
2142 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2143 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2145 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2150 CODE TOP_LCD \ LCD Sample
2151 \ \ if write : %xxxxWWWW --
2152 \ \ if read : -- %0000RRRR
2153 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2154 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2155 0= IF \ write LCD bits pattern
2157 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2158 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2161 THEN \ read LCD bits pattern
2164 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2165 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2170 CODE LCD_WRC \ char -- Write Char
2171 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2173 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2174 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2175 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2176 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2177 COLON \ high level word starts here
2178 TOP_LCD 2 20_US \ write high nibble first
2182 CODE LCD_WRF \ func -- Write Fonction
2183 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2187 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
2188 : LCD_HOME $02 LCD_WRF 100 20_us ;
2190 \ [UNDEFINED] OR [IF]
2192 \ \ https://forth-standard.org/standard/core/OR
2193 \ \ C OR x1 x2 -- x3 logical OR
2201 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
2202 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
2203 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
2204 \ : LCD_FN_SET $20 OR LCD_WrF ;
2205 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
2206 \ : LCD_GOTO $80 OR LCD_WrF ;
2209 \ CODE LCD_RDS \ -- status Read Status
2210 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2211 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2212 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2213 \ COLON \ starts a FORTH word
2214 \ TOP_LCD 2 20_us \ -- %0000HHHH
2215 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2216 \ HI2LO \ switch from FORTH to assembler
2217 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2218 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2219 \ MOV @RSP+,IP \ restore IP saved by COLON
2223 \ CODE LCD_RDC \ -- char Read Char
2224 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2229 \ ******************************\
2230 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2231 \ ******************************\
2232 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2233 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2234 BIT.B #SW2,&SW2_IN \ test switch S2
2235 0= IF \ case of switch S2 pressed
2236 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2238 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2241 BIT.B #SW1,&SW1_IN \ test switch S1 input
2242 0= IF \ case of Switch S1 pressed
2243 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2245 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2249 BW1 \ from quit on truncated RC5 message, repeated RC5 command
2253 \ ******************************\
2254 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2255 \ ******************************\
2256 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2257 \ ******************************\
2258 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2259 \ \ SMclock = 8|16|24 MHz
2260 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2261 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2262 \ \ SR(9)=new Toggle bit memory (ADD on)
2263 \ ******************************\
2264 \ RC5_FirstStartBitHalfCycle: \
2265 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2266 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2267 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
2268 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2270 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
2271 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2273 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
2274 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2276 MOV #1778,X \ RC5_Period * 1us
2277 MOV #14,W \ count of loop
2279 \ ******************************\
2280 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2281 \ ******************************\ |
2282 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2283 \ RC5_Compute_3/4_Period: \ |
2284 RRUM #1,X \ X=1/2 cycle |
2287 ADD X,Y \ Y=3/4 cycle
2288 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2290 \ ******************************\
2291 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2292 \ ******************************\
2293 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2294 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2295 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2296 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2297 SUB #1,W \ decrement count loop
2298 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2299 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2300 0<> WHILE \ ----> out of loop ----+
2301 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2303 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2304 CMP Y,X \ 1 | cycle time out of bound ?
2306 BIC #$30,&RC5_TIM_CTL \ | | stop timer
2307 GOTO BW1 \ | | quit on truncated RC5 message
2309 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2311 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2312 \ ******************************\ |
2313 \ RC5_SampleEndOf: \ <---------------------+
2314 \ ******************************\
2315 BIC #$30,&RC5_TIM_CTL \ stop timer
2316 \ ******************************\
2317 \ RC5_ComputeNewRC5word \
2318 \ ******************************\
2319 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2320 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2321 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2322 \ ******************************\
2323 \ RC5_ComputeC6bit \
2324 \ ******************************\
2325 BIT #BIT14,T \ test /C6 bit in T
2326 0= IF BIS #BIT6,X \ set C6 bit in X
2327 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2328 \ ******************************\
2329 \ RC5_CommandByteIsDone \ -- BASE RC5_code
2330 \ ******************************\
2331 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2332 \ ******************************\
2333 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2334 XOR @RSP,T \ (new XOR old) Toggle bits
2335 BIT #UF10,T \ repeated RC5_command ?
2336 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
2337 XOR #UF10,0(RSP) \ 5 toggle bit memory
2338 \ ******************************\
2339 \ Display IR_RC5 code \
2340 \ ******************************\
2341 SUB #8,PSP \ TOS -- x x x x TOS
2342 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
2343 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
2344 MOV #$10,&BASEADR \ set hexadecimal base
2345 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
2346 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
2347 LO2HI \ switch from assembler to FORTH
2348 LCD_CLEAR \ set LCD cursor at home
2349 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
2350 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2351 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
2352 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
2353 HI2LO \ -- switch from FORTH to assembler
2354 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
2355 MOV @PSP+,TOS \ -- TOS
2359 \ ------------------------------\
2361 \ ------------------------------\
2363 \ ... \ insert here your background task
2366 CALL &RXON \ comment this line to disable TERMINAL
2368 \ ******************************\
2369 \ here start all interrupts \
2370 \ ******************************\
2371 \ here return all interrupts \
2372 \ ******************************\
2376 \ ------------------------------\
2377 CODE STOP \ stops multitasking, must to be used before downloading app
2378 \ ------------------------------\
2379 \ restore default action of primary DEFERred word SLEEP (assembly version)
2380 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
2381 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
2382 MOV X,-2(X) \ restore the default background
2383 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
2384 ['] WARM >BODY IS WARM \ restore the default WARM
2386 ." RC5toLCD is removed. type START to restart"
2387 COLD \ performs reset to reset all interrupt vectors.
2390 \ ------------------------------\
2391 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
2392 \ ------------------------------\
2393 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2394 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2395 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2396 \ -- \ID input divider \ 10 = /4
2397 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2398 \ - \TBCLR TimerB Clear
2401 \ -------------------------------\
2402 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2403 \ -- \CM Capture Mode
2408 \ --- \OUTMOD \ 011 = set/reset
2414 \ -------------------------------\
2416 \ -------------------------------\
2418 \ ------------------------------\
2419 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2420 \ ------------------------------\
2421 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2422 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2423 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
2424 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2426 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
2427 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2429 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2430 \ ------------------------------\
2431 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2432 \ ------------------------------\
2433 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2434 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2435 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2436 \ ------------------------------\
2437 BIS.B #LCDVo,&LCDVo_DIR \
2438 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2439 \ ------------------------------\
2440 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2441 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2442 \ ------------------------------\
2443 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2444 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2445 \ ******************************\
2447 \ ******************************\
2448 BIS.B #RC5,&IR_IE \ enable RC5_Int
2449 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2450 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2451 \ ******************************\
2452 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2453 \ ******************************\
2454 \ %01 0001 0100 \ TAxCTL
2455 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2456 \ -- \ ID divided by 1
2457 \ -- \ MC MODE = up to TAxCCRn
2458 \ - \ TACLR clear timer count
2461 \ ------------------------------\
2462 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2463 \ ------------------------------\
2465 \ --- \ TAIDEX pre divisor
2466 \ ------------------------------\
2467 \ %0000 0000 0000 0101 \ TAxCCR0
2468 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2469 \ ------------------------------\
2470 \ %0000 0000 0001 0000 \ TAxCCTL0
2471 \ - \ CAP capture/compare mode = compare
2474 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2475 \ ------------------------------\
2476 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2477 \ ------------------------------\
2478 \ define LPM mode for ACCEPT \
2479 \ ------------------------------\
2480 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2481 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2482 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2483 \ ------------------------------\
2485 \ ------------------------------\
2486 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
2487 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
2488 \ ------------------------------\
2489 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
2490 \ ------------------------------\
2491 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
2492 \ CMP #2,Y \ Power_ON event
2493 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2495 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
2497 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
2499 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
2501 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
2502 \ ------------------------------\
2504 \ ------------------------------\
2506 \ ------------------------------\
2507 #1000 20_US \ 1- wait 20 ms
2508 %011 TOP_LCD \ 2- send DB5=DB4=1
2509 #205 20_US \ 3- wait 4,1 ms
2510 %011 TOP_LCD \ 4- send again DB5=DB4=1
2511 #5 20_US \ 5- wait 0,1 ms
2512 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2513 #2 20_US \ wait 40 us = LCD cycle
2514 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2515 #2 20_US \ wait 40 us = LCD cycle
2516 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2517 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2518 LCD_CLEAR \ 10- "LCD_Clear"
2519 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2520 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2521 LCD_CLEAR \ 10- "LCD_Clear"
2522 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2523 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2524 CR ." I love you" \ display message on LCD
2525 ['] CR >BODY IS CR \ CR executes its default value
2526 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2527 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2528 ABORT \ ...and end APP_INIT with ABORT, no return.
2531 \ ------------------------------\
2532 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
2533 \ ------------------------------\
2534 MOV #SLEEP,X \ replace default background process
2535 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
2536 MOV #WARM,X \ replace default WARM
2537 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
2538 MOV X,PC \ then execute it
2541 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
2545 CODE 20_US \ n -- n * 20 us
2546 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2548 BIT #1,&LCD_TIM_CTL \ 3
2549 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2550 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2552 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2557 CODE TOP_LCD \ LCD Sample
2558 \ \ if write : %xxxxWWWW --
2559 \ \ if read : -- %0000RRRR
2560 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2561 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2562 0= IF \ write LCD bits pattern
2564 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2565 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2568 THEN \ read LCD bits pattern
2571 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2572 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2577 CODE LCD_WRC \ char -- Write Char
2578 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2580 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2581 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2582 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2583 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2584 COLON \ high level word starts here
2585 TOP_LCD 2 20_US \ write high nibble first
2589 CODE LCD_WRF \ func -- Write Fonction
2590 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2594 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
2595 : LCD_HOME $02 LCD_WRF 100 20_us ;
2597 \ [UNDEFINED] OR [IF]
2599 \ \ https://forth-standard.org/standard/core/OR
2600 \ \ C OR x1 x2 -- x3 logical OR
2608 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
2609 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
2610 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
2611 \ : LCD_FN_SET $20 OR LCD_WrF ;
2612 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
2613 \ : LCD_GOTO $80 OR LCD_WrF ;
2616 \ CODE LCD_RDS \ -- status Read Status
2617 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2618 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2619 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2620 \ COLON \ starts a FORTH word
2621 \ TOP_LCD 2 20_us \ -- %0000HHHH
2622 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2623 \ HI2LO \ switch from FORTH to assembler
2624 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2625 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2626 \ MOV @RSP+,IP \ restore IP saved by COLON
2630 \ CODE LCD_RDC \ -- char Read Char
2631 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2636 \ ******************************\
2637 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2638 \ ******************************\
2639 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2640 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2641 BIT.B #SW2,&SW2_IN \ test switch S2
2642 0= IF \ case of switch S2 pressed
2643 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2645 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2648 BIT.B #SW1,&SW1_IN \ test switch S1 input
2649 0= IF \ case of Switch S1 pressed
2650 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2652 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2656 BW1 \ from quit on truncated RC5 message, repeated RC5 command
2660 \ ******************************\
2661 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2662 \ ******************************\
2663 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2664 \ ******************************\
2665 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2666 \ \ SMclock = 8|16|24 MHz
2667 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2668 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2669 \ \ SR(9)=new Toggle bit memory (ADD on)
2670 \ ******************************\
2671 \ RC5_FirstStartBitHalfCycle: \
2672 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2673 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2674 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
2675 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2677 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
2678 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2680 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
2681 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2683 MOV #1778,X \ RC5_Period * 1us
2684 MOV #14,W \ count of loop
2686 \ ******************************\
2687 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2688 \ ******************************\ |
2689 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2690 \ RC5_Compute_3/4_Period: \ |
2691 RRUM #1,X \ X=1/2 cycle |
2694 ADD X,Y \ Y=3/4 cycle
2695 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2697 \ ******************************\
2698 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2699 \ ******************************\
2700 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2701 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2702 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2703 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2704 SUB #1,W \ decrement count loop
2705 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2706 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2707 0<> WHILE \ ----> out of loop ----+
2708 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2710 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2711 CMP Y,X \ 1 | cycle time out of bound ?
2713 BIC #$30,&RC5_TIM_CTL \ | | stop timer
2714 GOTO BW1 \ | | quit on truncated RC5 message
2716 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2718 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2719 \ ******************************\ |
2720 \ RC5_SampleEndOf: \ <---------------------+
2721 \ ******************************\
2722 BIC #$30,&RC5_TIM_CTL \ stop timer
2723 \ ******************************\
2724 \ RC5_ComputeNewRC5word \
2725 \ ******************************\
2726 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2727 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2728 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2729 \ ******************************\
2730 \ RC5_ComputeC6bit \
2731 \ ******************************\
2732 BIT #BIT14,T \ test /C6 bit in T
2733 0= IF BIS #BIT6,X \ set C6 bit in X
2734 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2735 \ ******************************\
2736 \ RC5_CommandByteIsDone \ -- BASE RC5_code
2737 \ ******************************\
2738 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2739 \ ******************************\
2740 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2741 XOR @RSP,T \ (new XOR old) Toggle bits
2742 BIT #UF10,T \ repeated RC5_command ?
2743 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
2744 XOR #UF10,0(RSP) \ 5 toggle bit memory
2745 \ ******************************\
2746 \ Display IR_RC5 code \
2747 \ ******************************\
2748 SUB #8,PSP \ TOS -- x x x x TOS
2749 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
2750 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
2751 MOV #$10,&BASEADR \ set hexadecimal base
2752 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
2753 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
2754 LO2HI \ switch from assembler to FORTH
2755 LCD_CLEAR \ set LCD cursor at home
2756 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
2757 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2758 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
2759 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
2760 HI2LO \ -- switch from FORTH to assembler
2761 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
2762 MOV @PSP+,TOS \ -- TOS
2766 \ ------------------------------\
2768 \ ------------------------------\
2770 \ ... \ insert here your background task
2773 CALL &RXON \ comment this line to disable TERMINAL
2775 \ ******************************\
2776 \ here start all interrupts \
2777 \ ******************************\
2778 \ here return all interrupts \
2779 \ ******************************\
2783 \ ------------------------------\
2784 CODE STOP \ stops multitasking, must to be used before downloading app
2785 \ ------------------------------\
2786 \ restore default action of primary DEFERred word SLEEP (assembly version)
2787 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
2788 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
2789 MOV X,-2(X) \ restore the default background
2790 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
2791 ['] WARM >BODY IS WARM \ restore the default WARM
2793 ." RC5toLCD is removed. type START to restart"
2794 COLD \ performs reset to reset all interrupt vectors.
2797 \ ------------------------------\
2798 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
2799 \ ------------------------------\
2800 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2801 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2802 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2803 \ -- \ID input divider \ 10 = /4
2804 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2805 \ - \TBCLR TimerB Clear
2808 \ -------------------------------\
2809 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2810 \ -- \CM Capture Mode
2815 \ --- \OUTMOD \ 011 = set/reset
2821 \ -------------------------------\
2823 \ -------------------------------\
2825 \ ------------------------------\
2826 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2827 \ ------------------------------\
2828 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2829 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2830 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
2831 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2833 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
2834 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2836 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2837 \ ------------------------------\
2838 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2839 \ ------------------------------\
2840 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2841 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2842 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2843 \ ------------------------------\
2844 BIS.B #LCDVo,&LCDVo_DIR \
2845 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2846 \ ------------------------------\
2847 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2848 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2849 \ ------------------------------\
2850 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2851 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2852 \ ******************************\
2854 \ ******************************\
2855 BIS.B #RC5,&IR_IE \ enable RC5_Int
2856 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2857 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2858 \ ******************************\
2859 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2860 \ ******************************\
2861 \ %01 0001 0100 \ TAxCTL
2862 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2863 \ -- \ ID divided by 1
2864 \ -- \ MC MODE = up to TAxCCRn
2865 \ - \ TACLR clear timer count
2868 \ ------------------------------\
2869 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2870 \ ------------------------------\
2872 \ --- \ TAIDEX pre divisor
2873 \ ------------------------------\
2874 \ %0000 0000 0000 0101 \ TAxCCR0
2875 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2876 \ ------------------------------\
2877 \ %0000 0000 0001 0000 \ TAxCCTL0
2878 \ - \ CAP capture/compare mode = compare
2881 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2882 \ ------------------------------\
2883 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2884 \ ------------------------------\
2885 \ define LPM mode for ACCEPT \
2886 \ ------------------------------\
2887 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2888 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2889 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2890 \ ------------------------------\
2892 \ ------------------------------\
2893 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
2894 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
2895 \ ------------------------------\
2896 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
2897 \ ------------------------------\
2898 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
2899 \ CMP #2,Y \ Power_ON event
2900 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2902 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
2904 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
2906 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
2908 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
2909 \ ------------------------------\
2911 \ ------------------------------\
2913 \ ------------------------------\
2914 #1000 20_US \ 1- wait 20 ms
2915 %011 TOP_LCD \ 2- send DB5=DB4=1
2916 #205 20_US \ 3- wait 4,1 ms
2917 %011 TOP_LCD \ 4- send again DB5=DB4=1
2918 #5 20_US \ 5- wait 0,1 ms
2919 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2920 #2 20_US \ wait 40 us = LCD cycle
2921 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2922 #2 20_US \ wait 40 us = LCD cycle
2923 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2924 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2925 LCD_CLEAR \ 10- "LCD_Clear"
2926 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2927 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2928 LCD_CLEAR \ 10- "LCD_Clear"
2929 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2930 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2931 CR ." I love you" \ display message on LCD
2932 ['] CR >BODY IS CR \ CR executes its default value
2933 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2934 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2935 ABORT \ ...and end APP_INIT with ABORT, no return.
2938 \ ------------------------------\
2939 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
2940 \ ------------------------------\
2941 MOV #SLEEP,X \ replace default background process
2942 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
2943 MOV #WARM,X \ replace default WARM
2944 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
2945 MOV X,PC \ then execute it
2948 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
2952 CODE 20_US \ n -- n * 20 us
2953 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2955 BIT #1,&LCD_TIM_CTL \ 3
2956 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2957 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2959 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2964 CODE TOP_LCD \ LCD Sample
2965 \ \ if write : %xxxxWWWW --
2966 \ \ if read : -- %0000RRRR
2967 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2968 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2969 0= IF \ write LCD bits pattern
2971 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2972 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2975 THEN \ read LCD bits pattern
2978 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2979 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2984 CODE LCD_WRC \ char -- Write Char
2985 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2987 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2988 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2989 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2990 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2991 COLON \ high level word starts here
2992 TOP_LCD 2 20_US \ write high nibble first
2996 CODE LCD_WRF \ func -- Write Fonction
2997 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3001 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3002 : LCD_HOME $02 LCD_WRF 100 20_us ;
3004 \ [UNDEFINED] OR [IF]
3006 \ \ https://forth-standard.org/standard/core/OR
3007 \ \ C OR x1 x2 -- x3 logical OR
3015 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
3016 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
3017 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
3018 \ : LCD_FN_SET $20 OR LCD_WrF ;
3019 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
3020 \ : LCD_GOTO $80 OR LCD_WrF ;
3023 \ CODE LCD_RDS \ -- status Read Status
3024 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3025 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3026 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3027 \ COLON \ starts a FORTH word
3028 \ TOP_LCD 2 20_us \ -- %0000HHHH
3029 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3030 \ HI2LO \ switch from FORTH to assembler
3031 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3032 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3033 \ MOV @RSP+,IP \ restore IP saved by COLON
3037 \ CODE LCD_RDC \ -- char Read Char
3038 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3043 \ ******************************\
3044 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3045 \ ******************************\
3046 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3047 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3048 BIT.B #SW2,&SW2_IN \ test switch S2
3049 0= IF \ case of switch S2 pressed
3050 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3052 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3055 BIT.B #SW1,&SW1_IN \ test switch S1 input
3056 0= IF \ case of Switch S1 pressed
3057 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3059 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3063 BW1 \ from quit on truncated RC5 message, repeated RC5 command
3067 \ ******************************\
3068 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3069 \ ******************************\
3070 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3071 \ ******************************\
3072 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3073 \ \ SMclock = 8|16|24 MHz
3074 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3075 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3076 \ \ SR(9)=new Toggle bit memory (ADD on)
3077 \ ******************************\
3078 \ RC5_FirstStartBitHalfCycle: \
3079 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3080 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3081 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
3082 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3084 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
3085 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3087 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
3088 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3090 MOV #1778,X \ RC5_Period * 1us
3091 MOV #14,W \ count of loop
3093 \ ******************************\
3094 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3095 \ ******************************\ |
3096 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3097 \ RC5_Compute_3/4_Period: \ |
3098 RRUM #1,X \ X=1/2 cycle |
3101 ADD X,Y \ Y=3/4 cycle
3102 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3104 \ ******************************\
3105 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3106 \ ******************************\
3107 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3108 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3109 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3110 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3111 SUB #1,W \ decrement count loop
3112 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3113 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3114 0<> WHILE \ ----> out of loop ----+
3115 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3117 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3118 CMP Y,X \ 1 | cycle time out of bound ?
3120 BIC #$30,&RC5_TIM_CTL \ | | stop timer
3121 GOTO BW1 \ | | quit on truncated RC5 message
3123 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3125 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3126 \ ******************************\ |
3127 \ RC5_SampleEndOf: \ <---------------------+
3128 \ ******************************\
3129 BIC #$30,&RC5_TIM_CTL \ stop timer
3130 \ ******************************\
3131 \ RC5_ComputeNewRC5word \
3132 \ ******************************\
3133 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3134 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3135 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3136 \ ******************************\
3137 \ RC5_ComputeC6bit \
3138 \ ******************************\
3139 BIT #BIT14,T \ test /C6 bit in T
3140 0= IF BIS #BIT6,X \ set C6 bit in X
3141 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3142 \ ******************************\
3143 \ RC5_CommandByteIsDone \ -- BASE RC5_code
3144 \ ******************************\
3145 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3146 \ ******************************\
3147 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3148 XOR @RSP,T \ (new XOR old) Toggle bits
3149 BIT #UF10,T \ repeated RC5_command ?
3150 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
3151 XOR #UF10,0(RSP) \ 5 toggle bit memory
3152 \ ******************************\
3153 \ Display IR_RC5 code \
3154 \ ******************************\
3155 SUB #8,PSP \ TOS -- x x x x TOS
3156 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
3157 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
3158 MOV #$10,&BASEADR \ set hexadecimal base
3159 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
3160 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
3161 LO2HI \ switch from assembler to FORTH
3162 LCD_CLEAR \ set LCD cursor at home
3163 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
3164 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3165 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
3166 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
3167 HI2LO \ -- switch from FORTH to assembler
3168 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
3169 MOV @PSP+,TOS \ -- TOS
3173 \ ------------------------------\
3175 \ ------------------------------\
3177 \ ... \ insert here your background task
3180 CALL &RXON \ comment this line to disable TERMINAL
3182 \ ******************************\
3183 \ here start all interrupts \
3184 \ ******************************\
3185 \ here return all interrupts \
3186 \ ******************************\
3190 \ ------------------------------\
3191 CODE STOP \ stops multitasking, must to be used before downloading app
3192 \ ------------------------------\
3193 \ restore default action of primary DEFERred word SLEEP (assembly version)
3194 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
3195 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
3196 MOV X,-2(X) \ restore the default background
3197 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
3198 ['] WARM >BODY IS WARM \ restore the default WARM
3200 ." RC5toLCD is removed. type START to restart"
3201 COLD \ performs reset to reset all interrupt vectors.
3204 \ ------------------------------\
3205 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
3206 \ ------------------------------\
3207 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3208 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3209 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3210 \ -- \ID input divider \ 10 = /4
3211 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3212 \ - \TBCLR TimerB Clear
3215 \ -------------------------------\
3216 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3217 \ -- \CM Capture Mode
3222 \ --- \OUTMOD \ 011 = set/reset
3228 \ -------------------------------\
3230 \ -------------------------------\
3232 \ ------------------------------\
3233 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3234 \ ------------------------------\
3235 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3236 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3237 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
3238 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3240 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
3241 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3243 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3244 \ ------------------------------\
3245 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3246 \ ------------------------------\
3247 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3248 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3249 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3250 \ ------------------------------\
3251 BIS.B #LCDVo,&LCDVo_DIR \
3252 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3253 \ ------------------------------\
3254 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3255 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3256 \ ------------------------------\
3257 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3258 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3259 \ ******************************\
3261 \ ******************************\
3262 BIS.B #RC5,&IR_IE \ enable RC5_Int
3263 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3264 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3265 \ ******************************\
3266 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3267 \ ******************************\
3268 \ %01 0001 0100 \ TAxCTL
3269 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3270 \ -- \ ID divided by 1
3271 \ -- \ MC MODE = up to TAxCCRn
3272 \ - \ TACLR clear timer count
3275 \ ------------------------------\
3276 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3277 \ ------------------------------\
3279 \ --- \ TAIDEX pre divisor
3280 \ ------------------------------\
3281 \ %0000 0000 0000 0101 \ TAxCCR0
3282 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3283 \ ------------------------------\
3284 \ %0000 0000 0001 0000 \ TAxCCTL0
3285 \ - \ CAP capture/compare mode = compare
3288 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3289 \ ------------------------------\
3290 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3291 \ ------------------------------\
3292 \ define LPM mode for ACCEPT \
3293 \ ------------------------------\
3294 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3295 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3296 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3297 \ ------------------------------\
3299 \ ------------------------------\
3300 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
3301 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
3302 \ ------------------------------\
3303 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
3304 \ ------------------------------\
3305 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
3306 \ CMP #2,Y \ Power_ON event
3307 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3309 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
3311 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
3313 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
3315 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
3316 \ ------------------------------\
3318 \ ------------------------------\
3320 \ ------------------------------\
3321 #1000 20_US \ 1- wait 20 ms
3322 %011 TOP_LCD \ 2- send DB5=DB4=1
3323 #205 20_US \ 3- wait 4,1 ms
3324 %011 TOP_LCD \ 4- send again DB5=DB4=1
3325 #5 20_US \ 5- wait 0,1 ms
3326 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3327 #2 20_US \ wait 40 us = LCD cycle
3328 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3329 #2 20_US \ wait 40 us = LCD cycle
3330 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3331 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3332 LCD_CLEAR \ 10- "LCD_Clear"
3333 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3334 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3335 LCD_CLEAR \ 10- "LCD_Clear"
3336 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3337 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3338 CR ." I love you" \ display message on LCD
3339 ['] CR >BODY IS CR \ CR executes its default value
3340 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3341 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3342 ABORT \ ...and end APP_INIT with ABORT, no return.
3345 \ ------------------------------\
3346 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
3347 \ ------------------------------\
3348 MOV #SLEEP,X \ replace default background process
3349 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
3350 MOV #WARM,X \ replace default WARM
3351 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
3352 MOV X,PC \ then execute it
3355 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
3359 CODE 20_US \ n -- n * 20 us
3360 BEGIN \ here we presume that LCD_TIM_IFG = 1...
3362 BIT #1,&LCD_TIM_CTL \ 3
3363 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
3364 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
3366 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
3371 CODE TOP_LCD \ LCD Sample
3372 \ \ if write : %xxxxWWWW --
3373 \ \ if read : -- %0000RRRR
3374 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3375 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3376 0= IF \ write LCD bits pattern
3378 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3379 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3382 THEN \ read LCD bits pattern
3385 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3386 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3391 CODE LCD_WRC \ char -- Write Char
3392 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3394 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3395 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3396 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3397 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3398 COLON \ high level word starts here
3399 TOP_LCD 2 20_US \ write high nibble first
3403 CODE LCD_WRF \ func -- Write Fonction
3404 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3408 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3409 : LCD_HOME $02 LCD_WRF 100 20_us ;
3411 \ [UNDEFINED] OR [IF]
3413 \ \ https://forth-standard.org/standard/core/OR
3414 \ \ C OR x1 x2 -- x3 logical OR
3422 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
3423 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
3424 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
3425 \ : LCD_FN_SET $20 OR LCD_WrF ;
3426 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
3427 \ : LCD_GOTO $80 OR LCD_WrF ;
3430 \ CODE LCD_RDS \ -- status Read Status
3431 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3432 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3433 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3434 \ COLON \ starts a FORTH word
3435 \ TOP_LCD 2 20_us \ -- %0000HHHH
3436 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3437 \ HI2LO \ switch from FORTH to assembler
3438 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3439 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3440 \ MOV @RSP+,IP \ restore IP saved by COLON
3444 \ CODE LCD_RDC \ -- char Read Char
3445 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3450 \ ******************************\
3451 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3452 \ ******************************\
3453 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3454 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3455 BIT.B #SW2,&SW2_IN \ test switch S2
3456 0= IF \ case of switch S2 pressed
3457 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3459 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3462 BIT.B #SW1,&SW1_IN \ test switch S1 input
3463 0= IF \ case of Switch S1 pressed
3464 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3466 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3470 BW1 \ from quit on truncated RC5 message, repeated RC5 command
3474 \ ******************************\
3475 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3476 \ ******************************\
3477 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3478 \ ******************************\
3479 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3480 \ \ SMclock = 8|16|24 MHz
3481 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3482 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3483 \ \ SR(9)=new Toggle bit memory (ADD on)
3484 \ ******************************\
3485 \ RC5_FirstStartBitHalfCycle: \
3486 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3487 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3488 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
3489 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3491 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
3492 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3494 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
3495 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3497 MOV #1778,X \ RC5_Period * 1us
3498 MOV #14,W \ count of loop
3500 \ ******************************\
3501 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3502 \ ******************************\ |
3503 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3504 \ RC5_Compute_3/4_Period: \ |
3505 RRUM #1,X \ X=1/2 cycle |
3508 ADD X,Y \ Y=3/4 cycle
3509 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3511 \ ******************************\
3512 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3513 \ ******************************\
3514 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3515 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3516 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3517 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3518 SUB #1,W \ decrement count loop
3519 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3520 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3521 0<> WHILE \ ----> out of loop ----+
3522 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3524 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3525 CMP Y,X \ 1 | cycle time out of bound ?
3527 BIC #$30,&RC5_TIM_CTL \ | | stop timer
3528 GOTO BW1 \ | | quit on truncated RC5 message
3530 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3532 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3533 \ ******************************\ |
3534 \ RC5_SampleEndOf: \ <---------------------+
3535 \ ******************************\
3536 BIC #$30,&RC5_TIM_CTL \ stop timer
3537 \ ******************************\
3538 \ RC5_ComputeNewRC5word \
3539 \ ******************************\
3540 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3541 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3542 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3543 \ ******************************\
3544 \ RC5_ComputeC6bit \
3545 \ ******************************\
3546 BIT #BIT14,T \ test /C6 bit in T
3547 0= IF BIS #BIT6,X \ set C6 bit in X
3548 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3549 \ ******************************\
3550 \ RC5_CommandByteIsDone \ -- BASE RC5_code
3551 \ ******************************\
3552 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3553 \ ******************************\
3554 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3555 XOR @RSP,T \ (new XOR old) Toggle bits
3556 BIT #UF10,T \ repeated RC5_command ?
3557 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
3558 XOR #UF10,0(RSP) \ 5 toggle bit memory
3559 \ ******************************\
3560 \ Display IR_RC5 code \
3561 \ ******************************\
3562 SUB #8,PSP \ TOS -- x x x x TOS
3563 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
3564 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
3565 MOV #$10,&BASEADR \ set hexadecimal base
3566 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
3567 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
3568 LO2HI \ switch from assembler to FORTH
3569 LCD_CLEAR \ set LCD cursor at home
3570 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
3571 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3572 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
3573 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
3574 HI2LO \ -- switch from FORTH to assembler
3575 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
3576 MOV @PSP+,TOS \ -- TOS
3580 \ ------------------------------\
3582 \ ------------------------------\
3584 \ ... \ insert here your background task
3587 CALL &RXON \ comment this line to disable TERMINAL
3589 \ ******************************\
3590 \ here start all interrupts \
3591 \ ******************************\
3592 \ here return all interrupts \
3593 \ ******************************\
3597 \ ------------------------------\
3598 CODE STOP \ stops multitasking, must to be used before downloading app
3599 \ ------------------------------\
3600 \ restore default action of primary DEFERred word SLEEP (assembly version)
3601 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
3602 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
3603 MOV X,-2(X) \ restore the default background
3604 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
3605 ['] WARM >BODY IS WARM \ restore the default WARM
3607 ." RC5toLCD is removed. type START to restart"
3608 COLD \ performs reset to reset all interrupt vectors.
3611 \ ------------------------------\
3612 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
3613 \ ------------------------------\
3614 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3615 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3616 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3617 \ -- \ID input divider \ 10 = /4
3618 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3619 \ - \TBCLR TimerB Clear
3622 \ -------------------------------\
3623 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3624 \ -- \CM Capture Mode
3629 \ --- \OUTMOD \ 011 = set/reset
3635 \ -------------------------------\
3637 \ -------------------------------\
3639 \ ------------------------------\
3640 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3641 \ ------------------------------\
3642 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3643 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3644 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
3645 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3647 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
3648 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3650 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3651 \ ------------------------------\
3652 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3653 \ ------------------------------\
3654 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3655 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3656 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3657 \ ------------------------------\
3658 BIS.B #LCDVo,&LCDVo_DIR \
3659 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3660 \ ------------------------------\
3661 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3662 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3663 \ ------------------------------\
3664 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3665 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3666 \ ******************************\
3668 \ ******************************\
3669 BIS.B #RC5,&IR_IE \ enable RC5_Int
3670 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3671 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3672 \ ******************************\
3673 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3674 \ ******************************\
3675 \ %01 0001 0100 \ TAxCTL
3676 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3677 \ -- \ ID divided by 1
3678 \ -- \ MC MODE = up to TAxCCRn
3679 \ - \ TACLR clear timer count
3682 \ ------------------------------\
3683 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3684 \ ------------------------------\
3686 \ --- \ TAIDEX pre divisor
3687 \ ------------------------------\
3688 \ %0000 0000 0000 0101 \ TAxCCR0
3689 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3690 \ ------------------------------\
3691 \ %0000 0000 0001 0000 \ TAxCCTL0
3692 \ - \ CAP capture/compare mode = compare
3695 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3696 \ ------------------------------\
3697 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3698 \ ------------------------------\
3699 \ define LPM mode for ACCEPT \
3700 \ ------------------------------\
3701 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3702 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3703 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3704 \ ------------------------------\
3706 \ ------------------------------\
3707 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
3708 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
3709 \ ------------------------------\
3710 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
3711 \ ------------------------------\
3712 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
3713 \ CMP #2,Y \ Power_ON event
3714 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3716 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
3718 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
3720 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
3722 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
3723 \ ------------------------------\
3725 \ ------------------------------\
3727 \ ------------------------------\
3728 #1000 20_US \ 1- wait 20 ms
3729 %011 TOP_LCD \ 2- send DB5=DB4=1
3730 #205 20_US \ 3- wait 4,1 ms
3731 %011 TOP_LCD \ 4- send again DB5=DB4=1
3732 #5 20_US \ 5- wait 0,1 ms
3733 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3734 #2 20_US \ wait 40 us = LCD cycle
3735 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3736 #2 20_US \ wait 40 us = LCD cycle
3737 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3738 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3739 LCD_CLEAR \ 10- "LCD_Clear"
3740 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3741 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3742 LCD_CLEAR \ 10- "LCD_Clear"
3743 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3744 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3745 CR ." I love you" \ display message on LCD
3746 ['] CR >BODY IS CR \ CR executes its default value
3747 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3748 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3749 ABORT \ ...and end APP_INIT with ABORT, no return.
3752 \ ------------------------------\
3753 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
3754 \ ------------------------------\
3755 MOV #SLEEP,X \ replace default background process
3756 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
3757 MOV #WARM,X \ replace default WARM
3758 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
3759 MOV X,PC \ then execute it
3762 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
3766 CODE 20_US \ n -- n * 20 us
3767 BEGIN \ here we presume that LCD_TIM_IFG = 1...
3769 BIT #1,&LCD_TIM_CTL \ 3
3770 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
3771 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
3773 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
3778 CODE TOP_LCD \ LCD Sample
3779 \ \ if write : %xxxxWWWW --
3780 \ \ if read : -- %0000RRRR
3781 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3782 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3783 0= IF \ write LCD bits pattern
3785 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3786 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3789 THEN \ read LCD bits pattern
3792 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3793 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3798 CODE LCD_WRC \ char -- Write Char
3799 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3801 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3802 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3803 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3804 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3805 COLON \ high level word starts here
3806 TOP_LCD 2 20_US \ write high nibble first
3810 CODE LCD_WRF \ func -- Write Fonction
3811 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3815 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3816 : LCD_HOME $02 LCD_WRF 100 20_us ;
3818 \ [UNDEFINED] OR [IF]
3820 \ \ https://forth-standard.org/standard/core/OR
3821 \ \ C OR x1 x2 -- x3 logical OR
3829 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
3830 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
3831 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
3832 \ : LCD_FN_SET $20 OR LCD_WrF ;
3833 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
3834 \ : LCD_GOTO $80 OR LCD_WrF ;
3837 \ CODE LCD_RDS \ -- status Read Status
3838 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3839 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3840 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3841 \ COLON \ starts a FORTH word
3842 \ TOP_LCD 2 20_us \ -- %0000HHHH
3843 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3844 \ HI2LO \ switch from FORTH to assembler
3845 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3846 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3847 \ MOV @RSP+,IP \ restore IP saved by COLON
3851 \ CODE LCD_RDC \ -- char Read Char
3852 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3857 \ ******************************\
3858 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3859 \ ******************************\
3860 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3861 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3862 BIT.B #SW2,&SW2_IN \ test switch S2
3863 0= IF \ case of switch S2 pressed
3864 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3866 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3869 BIT.B #SW1,&SW1_IN \ test switch S1 input
3870 0= IF \ case of Switch S1 pressed
3871 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3873 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3877 BW1 \ from quit on truncated RC5 message, repeated RC5 command
3881 \ ******************************\
3882 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3883 \ ******************************\
3884 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3885 \ ******************************\
3886 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3887 \ \ SMclock = 8|16|24 MHz
3888 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3889 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3890 \ \ SR(9)=new Toggle bit memory (ADD on)
3891 \ ******************************\
3892 \ RC5_FirstStartBitHalfCycle: \
3893 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3894 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3895 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
3896 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3898 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
3899 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3901 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
3902 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3904 MOV #1778,X \ RC5_Period * 1us
3905 MOV #14,W \ count of loop
3907 \ ******************************\
3908 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3909 \ ******************************\ |
3910 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3911 \ RC5_Compute_3/4_Period: \ |
3912 RRUM #1,X \ X=1/2 cycle |
3915 ADD X,Y \ Y=3/4 cycle
3916 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3918 \ ******************************\
3919 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3920 \ ******************************\
3921 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3922 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3923 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3924 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3925 SUB #1,W \ decrement count loop
3926 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3927 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3928 0<> WHILE \ ----> out of loop ----+
3929 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3931 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3932 CMP Y,X \ 1 | cycle time out of bound ?
3934 BIC #$30,&RC5_TIM_CTL \ | | stop timer
3935 GOTO BW1 \ | | quit on truncated RC5 message
3937 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3939 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3940 \ ******************************\ |
3941 \ RC5_SampleEndOf: \ <---------------------+
3942 \ ******************************\
3943 BIC #$30,&RC5_TIM_CTL \ stop timer
3944 \ ******************************\
3945 \ RC5_ComputeNewRC5word \
3946 \ ******************************\
3947 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3948 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3949 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3950 \ ******************************\
3951 \ RC5_ComputeC6bit \
3952 \ ******************************\
3953 BIT #BIT14,T \ test /C6 bit in T
3954 0= IF BIS #BIT6,X \ set C6 bit in X
3955 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3956 \ ******************************\
3957 \ RC5_CommandByteIsDone \ -- BASE RC5_code
3958 \ ******************************\
3959 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3960 \ ******************************\
3961 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3962 XOR @RSP,T \ (new XOR old) Toggle bits
3963 BIT #UF10,T \ repeated RC5_command ?
3964 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
3965 XOR #UF10,0(RSP) \ 5 toggle bit memory
3966 \ ******************************\
3967 \ Display IR_RC5 code \
3968 \ ******************************\
3969 SUB #8,PSP \ TOS -- x x x x TOS
3970 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
3971 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
3972 MOV #$10,&BASEADR \ set hexadecimal base
3973 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
3974 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
3975 LO2HI \ switch from assembler to FORTH
3976 LCD_CLEAR \ set LCD cursor at home
3977 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
3978 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3979 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
3980 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
3981 HI2LO \ -- switch from FORTH to assembler
3982 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
3983 MOV @PSP+,TOS \ -- TOS
3987 \ ------------------------------\
3989 \ ------------------------------\
3991 \ ... \ insert here your background task
3994 CALL &RXON \ comment this line to disable TERMINAL
3996 \ ******************************\
3997 \ here start all interrupts \
3998 \ ******************************\
3999 \ here return all interrupts \
4000 \ ******************************\
4004 \ ------------------------------\
4005 CODE STOP \ stops multitasking, must to be used before downloading app
4006 \ ------------------------------\
4007 \ restore default action of primary DEFERred word SLEEP (assembly version)
4008 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
4009 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4010 MOV X,-2(X) \ restore the default background
4011 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4012 ['] WARM >BODY IS WARM \ restore the default WARM
4014 ." RC5toLCD is removed. type START to restart"
4015 COLD \ performs reset to reset all interrupt vectors.
4018 \ ------------------------------\
4019 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
4020 \ ------------------------------\
4021 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4022 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4023 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4024 \ -- \ID input divider \ 10 = /4
4025 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4026 \ - \TBCLR TimerB Clear
4029 \ -------------------------------\
4030 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4031 \ -- \CM Capture Mode
4036 \ --- \OUTMOD \ 011 = set/reset
4042 \ -------------------------------\
4044 \ -------------------------------\
4046 \ ------------------------------\
4047 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4048 \ ------------------------------\
4049 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4050 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4051 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4052 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4054 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4055 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4057 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4058 \ ------------------------------\
4059 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4060 \ ------------------------------\
4061 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4062 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4063 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4064 \ ------------------------------\
4065 BIS.B #LCDVo,&LCDVo_DIR \
4066 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4067 \ ------------------------------\
4068 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4069 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4070 \ ------------------------------\
4071 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4072 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4073 \ ******************************\
4075 \ ******************************\
4076 BIS.B #RC5,&IR_IE \ enable RC5_Int
4077 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4078 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4079 \ ******************************\
4080 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4081 \ ******************************\
4082 \ %01 0001 0100 \ TAxCTL
4083 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4084 \ -- \ ID divided by 1
4085 \ -- \ MC MODE = up to TAxCCRn
4086 \ - \ TACLR clear timer count
4089 \ ------------------------------\
4090 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4091 \ ------------------------------\
4093 \ --- \ TAIDEX pre divisor
4094 \ ------------------------------\
4095 \ %0000 0000 0000 0101 \ TAxCCR0
4096 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4097 \ ------------------------------\
4098 \ %0000 0000 0001 0000 \ TAxCCTL0
4099 \ - \ CAP capture/compare mode = compare
4102 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4103 \ ------------------------------\
4104 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4105 \ ------------------------------\
4106 \ define LPM mode for ACCEPT \
4107 \ ------------------------------\
4108 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4109 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4110 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4111 \ ------------------------------\
4113 \ ------------------------------\
4114 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
4115 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4116 \ ------------------------------\
4117 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4118 \ ------------------------------\
4119 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
4120 \ CMP #2,Y \ Power_ON event
4121 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4123 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
4125 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4127 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4129 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4130 \ ------------------------------\
4132 \ ------------------------------\
4134 \ ------------------------------\
4135 #1000 20_US \ 1- wait 20 ms
4136 %011 TOP_LCD \ 2- send DB5=DB4=1
4137 #205 20_US \ 3- wait 4,1 ms
4138 %011 TOP_LCD \ 4- send again DB5=DB4=1
4139 #5 20_US \ 5- wait 0,1 ms
4140 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4141 #2 20_US \ wait 40 us = LCD cycle
4142 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4143 #2 20_US \ wait 40 us = LCD cycle
4144 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4145 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4146 LCD_CLEAR \ 10- "LCD_Clear"
4147 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4148 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4149 LCD_CLEAR \ 10- "LCD_Clear"
4150 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4151 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4152 CR ." I love you" \ display message on LCD
4153 ['] CR >BODY IS CR \ CR executes its default value
4154 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4155 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
4156 ABORT \ ...and end APP_INIT with ABORT, no return.
4159 \ ------------------------------\
4160 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
4161 \ ------------------------------\
4162 MOV #SLEEP,X \ replace default background process
4163 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
4164 MOV #WARM,X \ replace default WARM
4165 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
4166 MOV X,PC \ then execute it
4169 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
4173 CODE 20_US \ n -- n * 20 us
4174 BEGIN \ here we presume that LCD_TIM_IFG = 1...
4176 BIT #1,&LCD_TIM_CTL \ 3
4177 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
4178 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
4180 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4185 CODE TOP_LCD \ LCD Sample
4186 \ \ if write : %xxxxWWWW --
4187 \ \ if read : -- %0000RRRR
4188 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4189 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4190 0= IF \ write LCD bits pattern
4192 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4193 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4196 THEN \ read LCD bits pattern
4199 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4200 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4205 CODE LCD_WRC \ char -- Write Char
4206 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4208 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4209 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4210 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4211 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4212 COLON \ high level word starts here
4213 TOP_LCD 2 20_US \ write high nibble first
4217 CODE LCD_WRF \ func -- Write Fonction
4218 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4222 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4223 : LCD_HOME $02 LCD_WRF 100 20_us ;
4225 \ [UNDEFINED] OR [IF]
4227 \ \ https://forth-standard.org/standard/core/OR
4228 \ \ C OR x1 x2 -- x3 logical OR
4236 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
4237 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
4238 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
4239 \ : LCD_FN_SET $20 OR LCD_WrF ;
4240 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
4241 \ : LCD_GOTO $80 OR LCD_WrF ;
4244 \ CODE LCD_RDS \ -- status Read Status
4245 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4246 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4247 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4248 \ COLON \ starts a FORTH word
4249 \ TOP_LCD 2 20_us \ -- %0000HHHH
4250 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4251 \ HI2LO \ switch from FORTH to assembler
4252 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4253 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4254 \ MOV @RSP+,IP \ restore IP saved by COLON
4258 \ CODE LCD_RDC \ -- char Read Char
4259 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4264 \ ******************************\
4265 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4266 \ ******************************\
4267 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4268 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4269 BIT.B #SW2,&SW2_IN \ test switch S2
4270 0= IF \ case of switch S2 pressed
4271 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4273 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4276 BIT.B #SW1,&SW1_IN \ test switch S1 input
4277 0= IF \ case of Switch S1 pressed
4278 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4280 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4284 BW1 \ from quit on truncated RC5 message, repeated RC5 command
4288 \ ******************************\
4289 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4290 \ ******************************\
4291 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4292 \ ******************************\
4293 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4294 \ \ SMclock = 8|16|24 MHz
4295 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4296 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4297 \ \ SR(9)=new Toggle bit memory (ADD on)
4298 \ ******************************\
4299 \ RC5_FirstStartBitHalfCycle: \
4300 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4301 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4302 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
4303 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4305 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
4306 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4308 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
4309 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4311 MOV #1778,X \ RC5_Period * 1us
4312 MOV #14,W \ count of loop
4314 \ ******************************\
4315 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4316 \ ******************************\ |
4317 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4318 \ RC5_Compute_3/4_Period: \ |
4319 RRUM #1,X \ X=1/2 cycle |
4322 ADD X,Y \ Y=3/4 cycle
4323 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4325 \ ******************************\
4326 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4327 \ ******************************\
4328 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4329 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4330 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4331 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4332 SUB #1,W \ decrement count loop
4333 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4334 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4335 0<> WHILE \ ----> out of loop ----+
4336 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4338 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4339 CMP Y,X \ 1 | cycle time out of bound ?
4341 BIC #$30,&RC5_TIM_CTL \ | | stop timer
4342 GOTO BW1 \ | | quit on truncated RC5 message
4344 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4346 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4347 \ ******************************\ |
4348 \ RC5_SampleEndOf: \ <---------------------+
4349 \ ******************************\
4350 BIC #$30,&RC5_TIM_CTL \ stop timer
4351 \ ******************************\
4352 \ RC5_ComputeNewRC5word \
4353 \ ******************************\
4354 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4355 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4356 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4357 \ ******************************\
4358 \ RC5_ComputeC6bit \
4359 \ ******************************\
4360 BIT #BIT14,T \ test /C6 bit in T
4361 0= IF BIS #BIT6,X \ set C6 bit in X
4362 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4363 \ ******************************\
4364 \ RC5_CommandByteIsDone \ -- BASE RC5_code
4365 \ ******************************\
4366 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4367 \ ******************************\
4368 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4369 XOR @RSP,T \ (new XOR old) Toggle bits
4370 BIT #UF10,T \ repeated RC5_command ?
4371 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
4372 XOR #UF10,0(RSP) \ 5 toggle bit memory
4373 \ ******************************\
4374 \ Display IR_RC5 code \
4375 \ ******************************\
4376 SUB #8,PSP \ TOS -- x x x x TOS
4377 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
4378 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
4379 MOV #$10,&BASEADR \ set hexadecimal base
4380 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
4381 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
4382 LO2HI \ switch from assembler to FORTH
4383 LCD_CLEAR \ set LCD cursor at home
4384 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
4385 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4386 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
4387 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
4388 HI2LO \ -- switch from FORTH to assembler
4389 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
4390 MOV @PSP+,TOS \ -- TOS
4394 \ ------------------------------\
4396 \ ------------------------------\
4398 \ ... \ insert here your background task
4401 CALL &RXON \ comment this line to disable TERMINAL
4403 \ ******************************\
4404 \ here start all interrupts \
4405 \ ******************************\
4406 \ here return all interrupts \
4407 \ ******************************\
4411 \ ------------------------------\
4412 CODE STOP \ stops multitasking, must to be used before downloading app
4413 \ ------------------------------\
4414 \ restore default action of primary DEFERred word SLEEP (assembly version)
4415 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
4416 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4417 MOV X,-2(X) \ restore the default background
4418 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4419 ['] WARM >BODY IS WARM \ restore the default WARM
4421 ." RC5toLCD is removed. type START to restart"
4422 COLD \ performs reset to reset all interrupt vectors.
4425 \ ------------------------------\
4426 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
4427 \ ------------------------------\
4428 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4429 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4430 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4431 \ -- \ID input divider \ 10 = /4
4432 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4433 \ - \TBCLR TimerB Clear
4436 \ -------------------------------\
4437 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4438 \ -- \CM Capture Mode
4443 \ --- \OUTMOD \ 011 = set/reset
4449 \ -------------------------------\
4451 \ -------------------------------\
4453 \ ------------------------------\
4454 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4455 \ ------------------------------\
4456 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4457 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4458 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4459 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4461 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4462 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4464 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4465 \ ------------------------------\
4466 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4467 \ ------------------------------\
4468 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4469 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4470 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4471 \ ------------------------------\
4472 BIS.B #LCDVo,&LCDVo_DIR \
4473 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4474 \ ------------------------------\
4475 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4476 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4477 \ ------------------------------\
4478 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4479 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4480 \ ******************************\
4482 \ ******************************\
4483 BIS.B #RC5,&IR_IE \ enable RC5_Int
4484 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4485 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4486 \ ******************************\
4487 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4488 \ ******************************\
4489 \ %01 0001 0100 \ TAxCTL
4490 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4491 \ -- \ ID divided by 1
4492 \ -- \ MC MODE = up to TAxCCRn
4493 \ - \ TACLR clear timer count
4496 \ ------------------------------\
4497 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4498 \ ------------------------------\
4500 \ --- \ TAIDEX pre divisor
4501 \ ------------------------------\
4502 \ %0000 0000 0000 0101 \ TAxCCR0
4503 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4504 \ ------------------------------\
4505 \ %0000 0000 0001 0000 \ TAxCCTL0
4506 \ - \ CAP capture/compare mode = compare
4509 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4510 \ ------------------------------\
4511 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4512 \ ------------------------------\
4513 \ define LPM mode for ACCEPT \
4514 \ ------------------------------\
4515 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4516 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4517 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4518 \ ------------------------------\
4520 \ ------------------------------\
4521 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
4522 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4523 \ ------------------------------\
4524 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4525 \ ------------------------------\
4526 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
4527 \ CMP #2,Y \ Power_ON event
4528 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4530 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
4532 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4534 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4536 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4537 \ ------------------------------\
4539 \ ------------------------------\
4541 \ ------------------------------\
4542 #1000 20_US \ 1- wait 20 ms
4543 %011 TOP_LCD \ 2- send DB5=DB4=1
4544 #205 20_US \ 3- wait 4,1 ms
4545 %011 TOP_LCD \ 4- send again DB5=DB4=1
4546 #5 20_US \ 5- wait 0,1 ms
4547 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4548 #2 20_US \ wait 40 us = LCD cycle
4549 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4550 #2 20_US \ wait 40 us = LCD cycle
4551 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4552 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4553 LCD_CLEAR \ 10- "LCD_Clear"
4554 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4555 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4556 LCD_CLEAR \ 10- "LCD_Clear"
4557 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4558 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4559 CR ." I love you" \ display message on LCD
4560 ['] CR >BODY IS CR \ CR executes its default value
4561 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4562 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
4563 ABORT \ ...and end APP_INIT with ABORT, no return.
4566 \ ------------------------------\
4567 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
4568 \ ------------------------------\
4569 MOV #SLEEP,X \ replace default background process
4570 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
4571 MOV #WARM,X \ replace default WARM
4572 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
4573 MOV X,PC \ then execute it
4576 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
4580 CODE 20_US \ n -- n * 20 us
4581 BEGIN \ here we presume that LCD_TIM_IFG = 1...
4583 BIT #1,&LCD_TIM_CTL \ 3
4584 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
4585 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
4587 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4592 CODE TOP_LCD \ LCD Sample
4593 \ \ if write : %xxxxWWWW --
4594 \ \ if read : -- %0000RRRR
4595 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4596 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4597 0= IF \ write LCD bits pattern
4599 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4600 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4603 THEN \ read LCD bits pattern
4606 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4607 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4612 CODE LCD_WRC \ char -- Write Char
4613 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4615 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4616 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4617 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4618 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4619 COLON \ high level word starts here
4620 TOP_LCD 2 20_US \ write high nibble first
4624 CODE LCD_WRF \ func -- Write Fonction
4625 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4629 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4630 : LCD_HOME $02 LCD_WRF 100 20_us ;
4632 \ [UNDEFINED] OR [IF]
4634 \ \ https://forth-standard.org/standard/core/OR
4635 \ \ C OR x1 x2 -- x3 logical OR
4643 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
4644 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
4645 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
4646 \ : LCD_FN_SET $20 OR LCD_WrF ;
4647 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
4648 \ : LCD_GOTO $80 OR LCD_WrF ;
4651 \ CODE LCD_RDS \ -- status Read Status
4652 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4653 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4654 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4655 \ COLON \ starts a FORTH word
4656 \ TOP_LCD 2 20_us \ -- %0000HHHH
4657 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4658 \ HI2LO \ switch from FORTH to assembler
4659 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4660 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4661 \ MOV @RSP+,IP \ restore IP saved by COLON
4665 \ CODE LCD_RDC \ -- char Read Char
4666 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4671 \ ******************************\
4672 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4673 \ ******************************\
4674 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4675 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4676 BIT.B #SW2,&SW2_IN \ test switch S2
4677 0= IF \ case of switch S2 pressed
4678 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4680 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4683 BIT.B #SW1,&SW1_IN \ test switch S1 input
4684 0= IF \ case of Switch S1 pressed
4685 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4687 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4691 BW1 \ from quit on truncated RC5 message, repeated RC5 command
4695 \ ******************************\
4696 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4697 \ ******************************\
4698 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4699 \ ******************************\
4700 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4701 \ \ SMclock = 8|16|24 MHz
4702 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4703 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4704 \ \ SR(9)=new Toggle bit memory (ADD on)
4705 \ ******************************\
4706 \ RC5_FirstStartBitHalfCycle: \
4707 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4708 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4709 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
4710 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4712 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
4713 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4715 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
4716 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4718 MOV #1778,X \ RC5_Period * 1us
4719 MOV #14,W \ count of loop
4721 \ ******************************\
4722 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4723 \ ******************************\ |
4724 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4725 \ RC5_Compute_3/4_Period: \ |
4726 RRUM #1,X \ X=1/2 cycle |
4729 ADD X,Y \ Y=3/4 cycle
4730 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4732 \ ******************************\
4733 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4734 \ ******************************\
4735 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4736 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4737 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4738 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4739 SUB #1,W \ decrement count loop
4740 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4741 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4742 0<> WHILE \ ----> out of loop ----+
4743 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4745 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4746 CMP Y,X \ 1 | cycle time out of bound ?
4748 BIC #$30,&RC5_TIM_CTL \ | | stop timer
4749 GOTO BW1 \ | | quit on truncated RC5 message
4751 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4753 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4754 \ ******************************\ |
4755 \ RC5_SampleEndOf: \ <---------------------+
4756 \ ******************************\
4757 BIC #$30,&RC5_TIM_CTL \ stop timer
4758 \ ******************************\
4759 \ RC5_ComputeNewRC5word \
4760 \ ******************************\
4761 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4762 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4763 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4764 \ ******************************\
4765 \ RC5_ComputeC6bit \
4766 \ ******************************\
4767 BIT #BIT14,T \ test /C6 bit in T
4768 0= IF BIS #BIT6,X \ set C6 bit in X
4769 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4770 \ ******************************\
4771 \ RC5_CommandByteIsDone \ -- BASE RC5_code
4772 \ ******************************\
4773 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4774 \ ******************************\
4775 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4776 XOR @RSP,T \ (new XOR old) Toggle bits
4777 BIT #UF10,T \ repeated RC5_command ?
4778 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
4779 XOR #UF10,0(RSP) \ 5 toggle bit memory
4780 \ ******************************\
4781 \ Display IR_RC5 code \
4782 \ ******************************\
4783 SUB #8,PSP \ TOS -- x x x x TOS
4784 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
4785 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
4786 MOV #$10,&BASEADR \ set hexadecimal base
4787 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
4788 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
4789 LO2HI \ switch from assembler to FORTH
4790 LCD_CLEAR \ set LCD cursor at home
4791 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
4792 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4793 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
4794 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
4795 HI2LO \ -- switch from FORTH to assembler
4796 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
4797 MOV @PSP+,TOS \ -- TOS
4801 \ ------------------------------\
4803 \ ------------------------------\
4805 \ ... \ insert here your background task
4808 CALL &RXON \ comment this line to disable TERMINAL
4810 \ ******************************\
4811 \ here start all interrupts \
4812 \ ******************************\
4813 \ here return all interrupts \
4814 \ ******************************\
4818 \ ------------------------------\
4819 CODE STOP \ stops multitasking, must to be used before downloading app
4820 \ ------------------------------\
4821 \ restore default action of primary DEFERred word SLEEP (assembly version)
4822 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
4823 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4824 MOV X,-2(X) \ restore the default background
4825 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4826 ['] WARM >BODY IS WARM \ restore the default WARM
4828 ." RC5toLCD is removed. type START to restart"
4829 COLD \ performs reset to reset all interrupt vectors.
4832 \ ------------------------------\
4833 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
4834 \ ------------------------------\
4835 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4836 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4837 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4838 \ -- \ID input divider \ 10 = /4
4839 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4840 \ - \TBCLR TimerB Clear
4843 \ -------------------------------\
4844 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4845 \ -- \CM Capture Mode
4850 \ --- \OUTMOD \ 011 = set/reset
4856 \ -------------------------------\
4858 \ -------------------------------\
4860 \ ------------------------------\
4861 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4862 \ ------------------------------\
4863 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4864 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4865 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4866 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4868 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4869 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4871 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4872 \ ------------------------------\
4873 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4874 \ ------------------------------\
4875 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4876 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4877 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4878 \ ------------------------------\
4879 BIS.B #LCDVo,&LCDVo_DIR \
4880 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4881 \ ------------------------------\
4882 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4883 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4884 \ ------------------------------\
4885 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4886 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4887 \ ******************************\
4889 \ ******************************\
4890 BIS.B #RC5,&IR_IE \ enable RC5_Int
4891 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4892 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4893 \ ******************************\
4894 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4895 \ ******************************\
4896 \ %01 0001 0100 \ TAxCTL
4897 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4898 \ -- \ ID divided by 1
4899 \ -- \ MC MODE = up to TAxCCRn
4900 \ - \ TACLR clear timer count
4903 \ ------------------------------\
4904 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4905 \ ------------------------------\
4907 \ --- \ TAIDEX pre divisor
4908 \ ------------------------------\
4909 \ %0000 0000 0000 0101 \ TAxCCR0
4910 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4911 \ ------------------------------\
4912 \ %0000 0000 0001 0000 \ TAxCCTL0
4913 \ - \ CAP capture/compare mode = compare
4916 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4917 \ ------------------------------\
4918 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4919 \ ------------------------------\
4920 \ define LPM mode for ACCEPT \
4921 \ ------------------------------\
4922 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4923 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4924 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4925 \ ------------------------------\
4927 \ ------------------------------\
4928 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
4929 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4930 \ ------------------------------\
4931 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4932 \ ------------------------------\
4933 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
4934 \ CMP #2,Y \ Power_ON event
4935 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4937 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
4939 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4941 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4943 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4944 \ ------------------------------\
4946 \ ------------------------------\
4948 \ ------------------------------\
4949 #1000 20_US \ 1- wait 20 ms
4950 %011 TOP_LCD \ 2- send DB5=DB4=1
4951 #205 20_US \ 3- wait 4,1 ms
4952 %011 TOP_LCD \ 4- send again DB5=DB4=1
4953 #5 20_US \ 5- wait 0,1 ms
4954 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4955 #2 20_US \ wait 40 us = LCD cycle
4956 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4957 #2 20_US \ wait 40 us = LCD cycle
4958 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4959 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4960 LCD_CLEAR \ 10- "LCD_Clear"
4961 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4962 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4963 LCD_CLEAR \ 10- "LCD_Clear"
4964 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4965 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4966 CR ." I love you" \ display message on LCD
4967 ['] CR >BODY IS CR \ CR executes its default value
4968 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4969 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
4970 ABORT \ ...and end APP_INIT with ABORT, no return.
4973 \ ------------------------------\
4974 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
4975 \ ------------------------------\
4976 MOV #SLEEP,X \ replace default background process
4977 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
4978 MOV #WARM,X \ replace default WARM
4979 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
4980 MOV X,PC \ then execute it
4983 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
4987 CODE 20_US \ n -- n * 20 us
4988 BEGIN \ here we presume that LCD_TIM_IFG = 1...
4990 BIT #1,&LCD_TIM_CTL \ 3
4991 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
4992 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
4994 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4999 CODE TOP_LCD \ LCD Sample
5000 \ \ if write : %xxxxWWWW --
5001 \ \ if read : -- %0000RRRR
5002 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5003 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5004 0= IF \ write LCD bits pattern
5006 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5007 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5010 THEN \ read LCD bits pattern
5013 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5014 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5019 CODE LCD_WRC \ char -- Write Char
5020 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5022 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5023 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5024 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5025 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5026 COLON \ high level word starts here
5027 TOP_LCD 2 20_US \ write high nibble first
5031 CODE LCD_WRF \ func -- Write Fonction
5032 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5036 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5037 : LCD_HOME $02 LCD_WRF 100 20_us ;
5039 \ [UNDEFINED] OR [IF]
5041 \ \ https://forth-standard.org/standard/core/OR
5042 \ \ C OR x1 x2 -- x3 logical OR
5050 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5051 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5052 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5053 \ : LCD_FN_SET $20 OR LCD_WrF ;
5054 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5055 \ : LCD_GOTO $80 OR LCD_WrF ;
5058 \ CODE LCD_RDS \ -- status Read Status
5059 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5060 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5061 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5062 \ COLON \ starts a FORTH word
5063 \ TOP_LCD 2 20_us \ -- %0000HHHH
5064 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5065 \ HI2LO \ switch from FORTH to assembler
5066 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5067 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5068 \ MOV @RSP+,IP \ restore IP saved by COLON
5072 \ CODE LCD_RDC \ -- char Read Char
5073 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5078 \ ******************************\
5079 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5080 \ ******************************\
5081 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5082 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5083 BIT.B #SW2,&SW2_IN \ test switch S2
5084 0= IF \ case of switch S2 pressed
5085 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5087 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5090 BIT.B #SW1,&SW1_IN \ test switch S1 input
5091 0= IF \ case of Switch S1 pressed
5092 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5094 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5098 BW1 \ from quit on truncated RC5 message, repeated RC5 command
5102 \ ******************************\
5103 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5104 \ ******************************\
5105 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5106 \ ******************************\
5107 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5108 \ \ SMclock = 8|16|24 MHz
5109 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5110 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5111 \ \ SR(9)=new Toggle bit memory (ADD on)
5112 \ ******************************\
5113 \ RC5_FirstStartBitHalfCycle: \
5114 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5115 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5116 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5117 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5119 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5120 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5122 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5123 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5125 MOV #1778,X \ RC5_Period * 1us
5126 MOV #14,W \ count of loop
5128 \ ******************************\
5129 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5130 \ ******************************\ |
5131 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5132 \ RC5_Compute_3/4_Period: \ |
5133 RRUM #1,X \ X=1/2 cycle |
5136 ADD X,Y \ Y=3/4 cycle
5137 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5139 \ ******************************\
5140 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5141 \ ******************************\
5142 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5143 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5144 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5145 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5146 SUB #1,W \ decrement count loop
5147 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
5148 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5149 0<> WHILE \ ----> out of loop ----+
5150 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5152 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
5153 CMP Y,X \ 1 | cycle time out of bound ?
5155 BIC #$30,&RC5_TIM_CTL \ | | stop timer
5156 GOTO BW1 \ | | quit on truncated RC5 message
5158 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
5160 REPEAT \ ----> loop back --+ | with X = new RC5_period value
5161 \ ******************************\ |
5162 \ RC5_SampleEndOf: \ <---------------------+
5163 \ ******************************\
5164 BIC #$30,&RC5_TIM_CTL \ stop timer
5165 \ ******************************\
5166 \ RC5_ComputeNewRC5word \
5167 \ ******************************\
5168 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
5169 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
5170 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
5171 \ ******************************\
5172 \ RC5_ComputeC6bit \
5173 \ ******************************\
5174 BIT #BIT14,T \ test /C6 bit in T
5175 0= IF BIS #BIT6,X \ set C6 bit in X
5176 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
5177 \ ******************************\
5178 \ RC5_CommandByteIsDone \ -- BASE RC5_code
5179 \ ******************************\
5180 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5181 \ ******************************\
5182 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
5183 XOR @RSP,T \ (new XOR old) Toggle bits
5184 BIT #UF10,T \ repeated RC5_command ?
5185 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
5186 XOR #UF10,0(RSP) \ 5 toggle bit memory
5187 \ ******************************\
5188 \ Display IR_RC5 code \
5189 \ ******************************\
5190 SUB #8,PSP \ TOS -- x x x x TOS
5191 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
5192 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
5193 MOV #$10,&BASEADR \ set hexadecimal base
5194 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
5195 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
5196 LO2HI \ switch from assembler to FORTH
5197 LCD_CLEAR \ set LCD cursor at home
5198 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
5199 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
5200 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
5201 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
5202 HI2LO \ -- switch from FORTH to assembler
5203 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
5204 MOV @PSP+,TOS \ -- TOS
5208 \ ------------------------------\
5210 \ ------------------------------\
5212 \ ... \ insert here your background task
5215 CALL &RXON \ comment this line to disable TERMINAL
5217 \ ******************************\
5218 \ here start all interrupts \
5219 \ ******************************\
5220 \ here return all interrupts \
5221 \ ******************************\
5225 \ ------------------------------\
5226 CODE STOP \ stops multitasking, must to be used before downloading app
5227 \ ------------------------------\
5228 \ restore default action of primary DEFERred word SLEEP (assembly version)
5229 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
5230 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
5231 MOV X,-2(X) \ restore the default background
5232 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
5233 ['] WARM >BODY IS WARM \ restore the default WARM
5235 ." RC5toLCD is removed. type START to restart"
5236 COLD \ performs reset to reset all interrupt vectors.
5239 \ ------------------------------\
5240 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
5241 \ ------------------------------\
5242 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
5243 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5244 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5245 \ -- \ID input divider \ 10 = /4
5246 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
5247 \ - \TBCLR TimerB Clear
5250 \ -------------------------------\
5251 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5252 \ -- \CM Capture Mode
5257 \ --- \OUTMOD \ 011 = set/reset
5263 \ -------------------------------\
5265 \ -------------------------------\
5267 \ ------------------------------\
5268 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
5269 \ ------------------------------\
5270 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
5271 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
5272 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
5273 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
5275 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
5276 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
5278 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
5279 \ ------------------------------\
5280 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
5281 \ ------------------------------\
5282 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
5283 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
5284 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5285 \ ------------------------------\
5286 BIS.B #LCDVo,&LCDVo_DIR \
5287 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
5288 \ ------------------------------\
5289 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5290 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5291 \ ------------------------------\
5292 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5293 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5294 \ ******************************\
5296 \ ******************************\
5297 BIS.B #RC5,&IR_IE \ enable RC5_Int
5298 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5299 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5300 \ ******************************\
5301 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
5302 \ ******************************\
5303 \ %01 0001 0100 \ TAxCTL
5304 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
5305 \ -- \ ID divided by 1
5306 \ -- \ MC MODE = up to TAxCCRn
5307 \ - \ TACLR clear timer count
5310 \ ------------------------------\
5311 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
5312 \ ------------------------------\
5314 \ --- \ TAIDEX pre divisor
5315 \ ------------------------------\
5316 \ %0000 0000 0000 0101 \ TAxCCR0
5317 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
5318 \ ------------------------------\
5319 \ %0000 0000 0001 0000 \ TAxCCTL0
5320 \ - \ CAP capture/compare mode = compare
5323 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
5324 \ ------------------------------\
5325 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
5326 \ ------------------------------\
5327 \ define LPM mode for ACCEPT \
5328 \ ------------------------------\
5329 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5330 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5331 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5332 \ ------------------------------\
5334 \ ------------------------------\
5335 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
5336 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
5337 \ ------------------------------\
5338 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
5339 \ ------------------------------\
5340 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
5341 \ CMP #2,Y \ Power_ON event
5342 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
5344 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
5346 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
5348 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
5350 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
5351 \ ------------------------------\
5353 \ ------------------------------\
5355 \ ------------------------------\
5356 #1000 20_US \ 1- wait 20 ms
5357 %011 TOP_LCD \ 2- send DB5=DB4=1
5358 #205 20_US \ 3- wait 4,1 ms
5359 %011 TOP_LCD \ 4- send again DB5=DB4=1
5360 #5 20_US \ 5- wait 0,1 ms
5361 %011 TOP_LCD \ 6- send again again DB5=DB4=1
5362 #2 20_US \ wait 40 us = LCD cycle
5363 %010 TOP_LCD \ 7- send DB5=1 DB4=0
5364 #2 20_US \ wait 40 us = LCD cycle
5365 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5366 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5367 LCD_CLEAR \ 10- "LCD_Clear"
5368 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5369 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5370 LCD_CLEAR \ 10- "LCD_Clear"
5371 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5372 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5373 CR ." I love you" \ display message on LCD
5374 ['] CR >BODY IS CR \ CR executes its default value
5375 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
5376 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5377 ABORT \ ...and end APP_INIT with ABORT, no return.
5380 \ ------------------------------\
5381 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
5382 \ ------------------------------\
5383 MOV #SLEEP,X \ replace default background process
5384 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
5385 MOV #WARM,X \ replace default WARM
5386 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
5387 MOV X,PC \ then execute it
5390 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
5394 CODE 20_US \ n -- n * 20 us
5395 BEGIN \ here we presume that LCD_TIM_IFG = 1...
5397 BIT #1,&LCD_TIM_CTL \ 3
5398 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
5399 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
5401 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
5406 CODE TOP_LCD \ LCD Sample
5407 \ \ if write : %xxxxWWWW --
5408 \ \ if read : -- %0000RRRR
5409 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5410 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5411 0= IF \ write LCD bits pattern
5413 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5414 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5417 THEN \ read LCD bits pattern
5420 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5421 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5426 CODE LCD_WRC \ char -- Write Char
5427 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5429 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5430 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5431 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5432 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5433 COLON \ high level word starts here
5434 TOP_LCD 2 20_US \ write high nibble first
5438 CODE LCD_WRF \ func -- Write Fonction
5439 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5443 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5444 : LCD_HOME $02 LCD_WRF 100 20_us ;
5446 \ [UNDEFINED] OR [IF]
5448 \ \ https://forth-standard.org/standard/core/OR
5449 \ \ C OR x1 x2 -- x3 logical OR
5457 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5458 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5459 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5460 \ : LCD_FN_SET $20 OR LCD_WrF ;
5461 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5462 \ : LCD_GOTO $80 OR LCD_WrF ;
5465 \ CODE LCD_RDS \ -- status Read Status
5466 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5467 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5468 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5469 \ COLON \ starts a FORTH word
5470 \ TOP_LCD 2 20_us \ -- %0000HHHH
5471 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5472 \ HI2LO \ switch from FORTH to assembler
5473 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5474 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5475 \ MOV @RSP+,IP \ restore IP saved by COLON
5479 \ CODE LCD_RDC \ -- char Read Char
5480 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5485 \ ******************************\
5486 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5487 \ ******************************\
5488 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5489 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5490 BIT.B #SW2,&SW2_IN \ test switch S2
5491 0= IF \ case of switch S2 pressed
5492 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5494 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5497 BIT.B #SW1,&SW1_IN \ test switch S1 input
5498 0= IF \ case of Switch S1 pressed
5499 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5501 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5505 BW1 \ from quit on truncated RC5 message, repeated RC5 command
5509 \ ******************************\
5510 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5511 \ ******************************\
5512 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5513 \ ******************************\
5514 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5515 \ \ SMclock = 8|16|24 MHz
5516 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5517 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5518 \ \ SR(9)=new Toggle bit memory (ADD on)
5519 \ ******************************\
5520 \ RC5_FirstStartBitHalfCycle: \
5521 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5522 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5523 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5524 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5526 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5527 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5529 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5530 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5532 MOV #1778,X \ RC5_Period * 1us
5533 MOV #14,W \ count of loop
5535 \ ******************************\
5536 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5537 \ ******************************\ |
5538 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5539 \ RC5_Compute_3/4_Period: \ |
5540 RRUM #1,X \ X=1/2 cycle |
5543 ADD X,Y \ Y=3/4 cycle
5544 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5546 \ ******************************\
5547 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5548 \ ******************************\
5549 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5550 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5551 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5552 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5553 SUB #1,W \ decrement count loop
5554 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
5555 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5556 0<> WHILE \ ----> out of loop ----+
5557 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5559 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
5560 CMP Y,X \ 1 | cycle time out of bound ?
5562 BIC #$30,&RC5_TIM_CTL \ | | stop timer
5563 GOTO BW1 \ | | quit on truncated RC5 message
5565 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
5567 REPEAT \ ----> loop back --+ | with X = new RC5_period value
5568 \ ******************************\ |
5569 \ RC5_SampleEndOf: \ <---------------------+
5570 \ ******************************\
5571 BIC #$30,&RC5_TIM_CTL \ stop timer
5572 \ ******************************\
5573 \ RC5_ComputeNewRC5word \
5574 \ ******************************\
5575 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
5576 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
5577 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
5578 \ ******************************\
5579 \ RC5_ComputeC6bit \
5580 \ ******************************\
5581 BIT #BIT14,T \ test /C6 bit in T
5582 0= IF BIS #BIT6,X \ set C6 bit in X
5583 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
5584 \ ******************************\
5585 \ RC5_CommandByteIsDone \ -- BASE RC5_code
5586 \ ******************************\
5587 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5588 \ ******************************\
5589 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
5590 XOR @RSP,T \ (new XOR old) Toggle bits
5591 BIT #UF10,T \ repeated RC5_command ?
5592 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
5593 XOR #UF10,0(RSP) \ 5 toggle bit memory
5594 \ ******************************\
5595 \ Display IR_RC5 code \
5596 \ ******************************\
5597 SUB #8,PSP \ TOS -- x x x x TOS
5598 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
5599 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
5600 MOV #$10,&BASEADR \ set hexadecimal base
5601 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
5602 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
5603 LO2HI \ switch from assembler to FORTH
5604 LCD_CLEAR \ set LCD cursor at home
5605 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
5606 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
5607 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
5608 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
5609 HI2LO \ -- switch from FORTH to assembler
5610 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
5611 MOV @PSP+,TOS \ -- TOS
5615 \ ------------------------------\
5617 \ ------------------------------\
5619 \ ... \ insert here your background task
5622 CALL &RXON \ comment this line to disable TERMINAL
5624 \ ******************************\
5625 \ here start all interrupts \
5626 \ ******************************\
5627 \ here return all interrupts \
5628 \ ******************************\
5632 \ ------------------------------\
5633 CODE STOP \ stops multitasking, must to be used before downloading app
5634 \ ------------------------------\
5635 \ restore default action of primary DEFERred word SLEEP (assembly version)
5636 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
5637 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
5638 MOV X,-2(X) \ restore the default background
5639 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
5640 ['] WARM >BODY IS WARM \ restore the default WARM
5642 ." RC5toLCD is removed. type START to restart"
5643 COLD \ performs reset to reset all interrupt vectors.
5646 \ ------------------------------\
5647 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
5648 \ ------------------------------\
5649 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
5650 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5651 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5652 \ -- \ID input divider \ 10 = /4
5653 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
5654 \ - \TBCLR TimerB Clear
5657 \ -------------------------------\
5658 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5659 \ -- \CM Capture Mode
5664 \ --- \OUTMOD \ 011 = set/reset
5670 \ -------------------------------\
5672 \ -------------------------------\
5674 \ ------------------------------\
5675 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
5676 \ ------------------------------\
5677 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
5678 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
5679 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
5680 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
5682 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
5683 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
5685 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
5686 \ ------------------------------\
5687 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
5688 \ ------------------------------\
5689 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
5690 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
5691 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5692 \ ------------------------------\
5693 BIS.B #LCDVo,&LCDVo_DIR \
5694 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
5695 \ ------------------------------\
5696 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5697 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5698 \ ------------------------------\
5699 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5700 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5701 \ ******************************\
5703 \ ******************************\
5704 BIS.B #RC5,&IR_IE \ enable RC5_Int
5705 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5706 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5707 \ ******************************\
5708 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
5709 \ ******************************\
5710 \ %01 0001 0100 \ TAxCTL
5711 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
5712 \ -- \ ID divided by 1
5713 \ -- \ MC MODE = up to TAxCCRn
5714 \ - \ TACLR clear timer count
5717 \ ------------------------------\
5718 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
5719 \ ------------------------------\
5721 \ --- \ TAIDEX pre divisor
5722 \ ------------------------------\
5723 \ %0000 0000 0000 0101 \ TAxCCR0
5724 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
5725 \ ------------------------------\
5726 \ %0000 0000 0001 0000 \ TAxCCTL0
5727 \ - \ CAP capture/compare mode = compare
5730 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
5731 \ ------------------------------\
5732 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
5733 \ ------------------------------\
5734 \ define LPM mode for ACCEPT \
5735 \ ------------------------------\
5736 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5737 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5738 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5739 \ ------------------------------\
5741 \ ------------------------------\
5742 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
5743 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
5744 \ ------------------------------\
5745 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
5746 \ ------------------------------\
5747 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
5748 \ CMP #2,Y \ Power_ON event
5749 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
5751 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
5753 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
5755 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
5757 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
5758 \ ------------------------------\
5760 \ ------------------------------\
5762 \ ------------------------------\
5763 #1000 20_US \ 1- wait 20 ms
5764 %011 TOP_LCD \ 2- send DB5=DB4=1
5765 #205 20_US \ 3- wait 4,1 ms
5766 %011 TOP_LCD \ 4- send again DB5=DB4=1
5767 #5 20_US \ 5- wait 0,1 ms
5768 %011 TOP_LCD \ 6- send again again DB5=DB4=1
5769 #2 20_US \ wait 40 us = LCD cycle
5770 %010 TOP_LCD \ 7- send DB5=1 DB4=0
5771 #2 20_US \ wait 40 us = LCD cycle
5772 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5773 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5774 LCD_CLEAR \ 10- "LCD_Clear"
5775 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5776 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5777 LCD_CLEAR \ 10- "LCD_Clear"
5778 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5779 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5780 CR ." I love you" \ display message on LCD
5781 ['] CR >BODY IS CR \ CR executes its default value
5782 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
5783 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5784 ABORT \ ...and end APP_INIT with ABORT, no return.
5787 \ ------------------------------\
5788 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
5789 \ ------------------------------\
5790 MOV #SLEEP,X \ replace default background process
5791 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
5792 MOV #WARM,X \ replace default WARM
5793 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
5794 MOV X,PC \ then execute it
5797 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
5801 CODE 20_US \ n -- n * 20 us
5802 BEGIN \ here we presume that LCD_TIM_IFG = 1...
5804 BIT #1,&LCD_TIM_CTL \ 3
5805 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
5806 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
5808 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
5813 CODE TOP_LCD \ LCD Sample
5814 \ \ if write : %xxxxWWWW --
5815 \ \ if read : -- %0000RRRR
5816 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5817 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5818 0= IF \ write LCD bits pattern
5820 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5821 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5824 THEN \ read LCD bits pattern
5827 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5828 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5833 CODE LCD_WRC \ char -- Write Char
5834 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5836 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5837 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5838 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5839 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5840 COLON \ high level word starts here
5841 TOP_LCD 2 20_US \ write high nibble first
5845 CODE LCD_WRF \ func -- Write Fonction
5846 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5850 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5851 : LCD_HOME $02 LCD_WRF 100 20_us ;
5853 \ [UNDEFINED] OR [IF]
5855 \ \ https://forth-standard.org/standard/core/OR
5856 \ \ C OR x1 x2 -- x3 logical OR
5864 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5865 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5866 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5867 \ : LCD_FN_SET $20 OR LCD_WrF ;
5868 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5869 \ : LCD_GOTO $80 OR LCD_WrF ;
5872 \ CODE LCD_RDS \ -- status Read Status
5873 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5874 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5875 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5876 \ COLON \ starts a FORTH word
5877 \ TOP_LCD 2 20_us \ -- %0000HHHH
5878 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5879 \ HI2LO \ switch from FORTH to assembler
5880 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5881 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5882 \ MOV @RSP+,IP \ restore IP saved by COLON
5886 \ CODE LCD_RDC \ -- char Read Char
5887 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5892 \ ******************************\
5893 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5894 \ ******************************\
5895 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5896 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5897 BIT.B #SW2,&SW2_IN \ test switch S2
5898 0= IF \ case of switch S2 pressed
5899 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5901 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5904 BIT.B #SW1,&SW1_IN \ test switch S1 input
5905 0= IF \ case of Switch S1 pressed
5906 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5908 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5912 BW1 \ from quit on truncated RC5 message, repeated RC5 command
5916 \ ******************************\
5917 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5918 \ ******************************\
5919 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5920 \ ******************************\
5921 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5922 \ \ SMclock = 8|16|24 MHz
5923 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5924 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5925 \ \ SR(9)=new Toggle bit memory (ADD on)
5926 \ ******************************\
5927 \ RC5_FirstStartBitHalfCycle: \
5928 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5929 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5930 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5931 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5933 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5934 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5936 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5937 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5939 MOV #1778,X \ RC5_Period * 1us
5940 MOV #14,W \ count of loop
5942 \ ******************************\
5943 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5944 \ ******************************\ |
5945 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5946 \ RC5_Compute_3/4_Period: \ |
5947 RRUM #1,X \ X=1/2 cycle |
5950 ADD X,Y \ Y=3/4 cycle
5951 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5953 \ ******************************\
5954 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5955 \ ******************************\
5956 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5957 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5958 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5959 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5960 SUB #1,W \ decrement count loop
5961 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
5962 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5963 0<> WHILE \ ----> out of loop ----+
5964 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5966 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
5967 CMP Y,X \ 1 | cycle time out of bound ?
5969 BIC #$30,&RC5_TIM_CTL \ | | stop timer
5970 GOTO BW1 \ | | quit on truncated RC5 message
5972 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
5974 REPEAT \ ----> loop back --+ | with X = new RC5_period value
5975 \ ******************************\ |
5976 \ RC5_SampleEndOf: \ <---------------------+
5977 \ ******************************\
5978 BIC #$30,&RC5_TIM_CTL \ stop timer
5979 \ ******************************\
5980 \ RC5_ComputeNewRC5word \
5981 \ ******************************\
5982 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
5983 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
5984 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
5985 \ ******************************\
5986 \ RC5_ComputeC6bit \
5987 \ ******************************\
5988 BIT #BIT14,T \ test /C6 bit in T
5989 0= IF BIS #BIT6,X \ set C6 bit in X
5990 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
5991 \ ******************************\
5992 \ RC5_CommandByteIsDone \ -- BASE RC5_code
5993 \ ******************************\
5994 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5995 \ ******************************\
5996 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
5997 XOR @RSP,T \ (new XOR old) Toggle bits
5998 BIT #UF10,T \ repeated RC5_command ?
5999 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
6000 XOR #UF10,0(RSP) \ 5 toggle bit memory
6001 \ ******************************\
6002 \ Display IR_RC5 code \
6003 \ ******************************\
6004 SUB #8,PSP \ TOS -- x x x x TOS
6005 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6006 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6007 MOV #$10,&BASEADR \ set hexadecimal base
6008 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6009 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6010 LO2HI \ switch from assembler to FORTH
6011 LCD_CLEAR \ set LCD cursor at home
6012 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6013 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
6014 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
6015 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
6016 HI2LO \ -- switch from FORTH to assembler
6017 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
6018 MOV @PSP+,TOS \ -- TOS
6022 \ ------------------------------\
6024 \ ------------------------------\
6026 \ ... \ insert here your background task
6029 CALL &RXON \ comment this line to disable TERMINAL
6031 \ ******************************\
6032 \ here start all interrupts \
6033 \ ******************************\
6034 \ here return all interrupts \
6035 \ ******************************\
6039 \ ------------------------------\
6040 CODE STOP \ stops multitasking, must to be used before downloading app
6041 \ ------------------------------\
6042 \ restore default action of primary DEFERred word SLEEP (assembly version)
6043 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
6044 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6045 MOV X,-2(X) \ restore the default background
6046 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
6047 ['] WARM >BODY IS WARM \ restore the default WARM
6049 ." RC5toLCD is removed. type START to restart"
6050 COLD \ performs reset to reset all interrupt vectors.
6053 \ ------------------------------\
6054 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
6055 \ ------------------------------\
6056 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
6057 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6058 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6059 \ -- \ID input divider \ 10 = /4
6060 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6061 \ - \TBCLR TimerB Clear
6064 \ -------------------------------\
6065 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6066 \ -- \CM Capture Mode
6071 \ --- \OUTMOD \ 011 = set/reset
6077 \ -------------------------------\
6079 \ -------------------------------\
6081 \ ------------------------------\
6082 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6083 \ ------------------------------\
6084 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6085 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6086 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6087 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6089 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6090 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6092 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6093 \ ------------------------------\
6094 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6095 \ ------------------------------\
6096 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6097 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6098 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6099 \ ------------------------------\
6100 BIS.B #LCDVo,&LCDVo_DIR \
6101 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6102 \ ------------------------------\
6103 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6104 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6105 \ ------------------------------\
6106 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6107 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6108 \ ******************************\
6110 \ ******************************\
6111 BIS.B #RC5,&IR_IE \ enable RC5_Int
6112 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6113 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6114 \ ******************************\
6115 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6116 \ ******************************\
6117 \ %01 0001 0100 \ TAxCTL
6118 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6119 \ -- \ ID divided by 1
6120 \ -- \ MC MODE = up to TAxCCRn
6121 \ - \ TACLR clear timer count
6124 \ ------------------------------\
6125 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6126 \ ------------------------------\
6128 \ --- \ TAIDEX pre divisor
6129 \ ------------------------------\
6130 \ %0000 0000 0000 0101 \ TAxCCR0
6131 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6132 \ ------------------------------\
6133 \ %0000 0000 0001 0000 \ TAxCCTL0
6134 \ - \ CAP capture/compare mode = compare
6137 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6138 \ ------------------------------\
6139 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6140 \ ------------------------------\
6141 \ define LPM mode for ACCEPT \
6142 \ ------------------------------\
6143 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6144 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6145 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6146 \ ------------------------------\
6148 \ ------------------------------\
6149 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
6150 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6151 \ ------------------------------\
6152 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6153 \ ------------------------------\
6154 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
6155 \ CMP #2,Y \ Power_ON event
6156 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
6158 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
6160 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
6162 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
6164 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
6165 \ ------------------------------\
6167 \ ------------------------------\
6169 \ ------------------------------\
6170 #1000 20_US \ 1- wait 20 ms
6171 %011 TOP_LCD \ 2- send DB5=DB4=1
6172 #205 20_US \ 3- wait 4,1 ms
6173 %011 TOP_LCD \ 4- send again DB5=DB4=1
6174 #5 20_US \ 5- wait 0,1 ms
6175 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6176 #2 20_US \ wait 40 us = LCD cycle
6177 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6178 #2 20_US \ wait 40 us = LCD cycle
6179 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6180 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6181 LCD_CLEAR \ 10- "LCD_Clear"
6182 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6183 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6184 LCD_CLEAR \ 10- "LCD_Clear"
6185 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6186 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6187 CR ." I love you" \ display message on LCD
6188 ['] CR >BODY IS CR \ CR executes its default value
6189 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
6190 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6191 ABORT \ ...and end APP_INIT with ABORT, no return.
6194 \ ------------------------------\
6195 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
6196 \ ------------------------------\
6197 MOV #SLEEP,X \ replace default background process
6198 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
6199 MOV #WARM,X \ replace default WARM
6200 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
6201 MOV X,PC \ then execute it
6204 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
6208 CODE 20_US \ n -- n * 20 us
6209 BEGIN \ here we presume that LCD_TIM_IFG = 1...
6211 BIT #1,&LCD_TIM_CTL \ 3
6212 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
6213 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
6215 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
6220 CODE TOP_LCD \ LCD Sample
6221 \ \ if write : %xxxxWWWW --
6222 \ \ if read : -- %0000RRRR
6223 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6224 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6225 0= IF \ write LCD bits pattern
6227 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6228 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6231 THEN \ read LCD bits pattern
6234 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6235 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6240 CODE LCD_WRC \ char -- Write Char
6241 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6243 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
6244 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
6245 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6246 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6247 COLON \ high level word starts here
6248 TOP_LCD 2 20_US \ write high nibble first
6252 CODE LCD_WRF \ func -- Write Fonction
6253 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6257 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
6258 : LCD_HOME $02 LCD_WRF 100 20_us ;
6260 \ [UNDEFINED] OR [IF]
6262 \ \ https://forth-standard.org/standard/core/OR
6263 \ \ C OR x1 x2 -- x3 logical OR
6271 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
6272 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
6273 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
6274 \ : LCD_FN_SET $20 OR LCD_WrF ;
6275 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
6276 \ : LCD_GOTO $80 OR LCD_WrF ;
6279 \ CODE LCD_RDS \ -- status Read Status
6280 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6281 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6282 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6283 \ COLON \ starts a FORTH word
6284 \ TOP_LCD 2 20_us \ -- %0000HHHH
6285 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6286 \ HI2LO \ switch from FORTH to assembler
6287 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6288 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6289 \ MOV @RSP+,IP \ restore IP saved by COLON
6293 \ CODE LCD_RDC \ -- char Read Char
6294 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6299 \ ******************************\
6300 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6301 \ ******************************\
6302 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
6303 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
6304 BIT.B #SW2,&SW2_IN \ test switch S2
6305 0= IF \ case of switch S2 pressed
6306 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
6308 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
6311 BIT.B #SW1,&SW1_IN \ test switch S1 input
6312 0= IF \ case of Switch S1 pressed
6313 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
6315 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
6319 BW1 \ from quit on truncated RC5 message, repeated RC5 command
6323 \ ******************************\
6324 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6325 \ ******************************\
6326 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6327 \ ******************************\
6328 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6329 \ \ SMclock = 8|16|24 MHz
6330 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
6331 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
6332 \ \ SR(9)=new Toggle bit memory (ADD on)
6333 \ ******************************\
6334 \ RC5_FirstStartBitHalfCycle: \
6335 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
6336 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
6337 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
6338 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
6340 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
6341 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
6343 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
6344 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
6346 MOV #1778,X \ RC5_Period * 1us
6347 MOV #14,W \ count of loop
6349 \ ******************************\
6350 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
6351 \ ******************************\ |
6352 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
6353 \ RC5_Compute_3/4_Period: \ |
6354 RRUM #1,X \ X=1/2 cycle |
6357 ADD X,Y \ Y=3/4 cycle
6358 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
6360 \ ******************************\
6361 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
6362 \ ******************************\
6363 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6364 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
6365 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6366 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6367 SUB #1,W \ decrement count loop
6368 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
6369 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6370 0<> WHILE \ ----> out of loop ----+
6371 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6373 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
6374 CMP Y,X \ 1 | cycle time out of bound ?
6376 BIC #$30,&RC5_TIM_CTL \ | | stop timer
6377 GOTO BW1 \ | | quit on truncated RC5 message
6379 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
6381 REPEAT \ ----> loop back --+ | with X = new RC5_period value
6382 \ ******************************\ |
6383 \ RC5_SampleEndOf: \ <---------------------+
6384 \ ******************************\
6385 BIC #$30,&RC5_TIM_CTL \ stop timer
6386 \ ******************************\
6387 \ RC5_ComputeNewRC5word \
6388 \ ******************************\
6389 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
6390 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
6391 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
6392 \ ******************************\
6393 \ RC5_ComputeC6bit \
6394 \ ******************************\
6395 BIT #BIT14,T \ test /C6 bit in T
6396 0= IF BIS #BIT6,X \ set C6 bit in X
6397 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
6398 \ ******************************\
6399 \ RC5_CommandByteIsDone \ -- BASE RC5_code
6400 \ ******************************\
6401 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6402 \ ******************************\
6403 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
6404 XOR @RSP,T \ (new XOR old) Toggle bits
6405 BIT #UF10,T \ repeated RC5_command ?
6406 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
6407 XOR #UF10,0(RSP) \ 5 toggle bit memory
6408 \ ******************************\
6409 \ Display IR_RC5 code \
6410 \ ******************************\
6411 SUB #8,PSP \ TOS -- x x x x TOS
6412 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6413 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6414 MOV #$10,&BASEADR \ set hexadecimal base
6415 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6416 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6417 LO2HI \ switch from assembler to FORTH
6418 LCD_CLEAR \ set LCD cursor at home
6419 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6420 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
6421 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
6422 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
6423 HI2LO \ -- switch from FORTH to assembler
6424 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
6425 MOV @PSP+,TOS \ -- TOS
6429 \ ------------------------------\
6431 \ ------------------------------\
6433 \ ... \ insert here your background task
6436 CALL &RXON \ comment this line to disable TERMINAL
6438 \ ******************************\
6439 \ here start all interrupts \
6440 \ ******************************\
6441 \ here return all interrupts \
6442 \ ******************************\
6446 \ ------------------------------\
6447 CODE STOP \ stops multitasking, must to be used before downloading app
6448 \ ------------------------------\
6449 \ restore default action of primary DEFERred word SLEEP (assembly version)
6450 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
6451 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6452 MOV X,-2(X) \ restore the default background
6453 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
6454 ['] WARM >BODY IS WARM \ restore the default WARM
6456 ." RC5toLCD is removed. type START to restart"
6457 COLD \ performs reset to reset all interrupt vectors.
6460 \ ------------------------------\
6461 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
6462 \ ------------------------------\
6463 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
6464 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6465 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6466 \ -- \ID input divider \ 10 = /4
6467 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6468 \ - \TBCLR TimerB Clear
6471 \ -------------------------------\
6472 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6473 \ -- \CM Capture Mode
6478 \ --- \OUTMOD \ 011 = set/reset
6484 \ -------------------------------\
6486 \ -------------------------------\
6488 \ ------------------------------\
6489 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6490 \ ------------------------------\
6491 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6492 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6493 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6494 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6496 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6497 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6499 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6500 \ ------------------------------\
6501 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6502 \ ------------------------------\
6503 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6504 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6505 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6506 \ ------------------------------\
6507 BIS.B #LCDVo,&LCDVo_DIR \
6508 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6509 \ ------------------------------\
6510 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6511 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6512 \ ------------------------------\
6513 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6514 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6515 \ ******************************\
6517 \ ******************************\
6518 BIS.B #RC5,&IR_IE \ enable RC5_Int
6519 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6520 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6521 \ ******************************\
6522 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6523 \ ******************************\
6524 \ %01 0001 0100 \ TAxCTL
6525 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6526 \ -- \ ID divided by 1
6527 \ -- \ MC MODE = up to TAxCCRn
6528 \ - \ TACLR clear timer count
6531 \ ------------------------------\
6532 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6533 \ ------------------------------\
6535 \ --- \ TAIDEX pre divisor
6536 \ ------------------------------\
6537 \ %0000 0000 0000 0101 \ TAxCCR0
6538 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6539 \ ------------------------------\
6540 \ %0000 0000 0001 0000 \ TAxCCTL0
6541 \ - \ CAP capture/compare mode = compare
6544 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6545 \ ------------------------------\
6546 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6547 \ ------------------------------\
6548 \ define LPM mode for ACCEPT \
6549 \ ------------------------------\
6550 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6551 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6552 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6553 \ ------------------------------\
6555 \ ------------------------------\
6556 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
6557 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6558 \ ------------------------------\
6559 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6560 \ ------------------------------\
6561 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
6562 \ CMP #2,Y \ Power_ON event
6563 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
6565 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
6567 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
6569 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
6571 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
6572 \ ------------------------------\
6574 \ ------------------------------\
6576 \ ------------------------------\
6577 #1000 20_US \ 1- wait 20 ms
6578 %011 TOP_LCD \ 2- send DB5=DB4=1
6579 #205 20_US \ 3- wait 4,1 ms
6580 %011 TOP_LCD \ 4- send again DB5=DB4=1
6581 #5 20_US \ 5- wait 0,1 ms
6582 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6583 #2 20_US \ wait 40 us = LCD cycle
6584 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6585 #2 20_US \ wait 40 us = LCD cycle
6586 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6587 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6588 LCD_CLEAR \ 10- "LCD_Clear"
6589 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6590 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6591 LCD_CLEAR \ 10- "LCD_Clear"
6592 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6593 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6594 CR ." I love you" \ display message on LCD
6595 ['] CR >BODY IS CR \ CR executes its default value
6596 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
6597 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6598 ABORT \ ...and end APP_INIT with ABORT, no return.
6601 \ ------------------------------\
6602 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
6603 \ ------------------------------\
6604 MOV #SLEEP,X \ replace default background process
6605 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
6606 MOV #WARM,X \ replace default WARM
6607 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
6608 MOV X,PC \ then execute it
6611 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
6615 CODE 20_US \ n -- n * 20 us
6616 BEGIN \ here we presume that LCD_TIM_IFG = 1...
6618 BIT #1,&LCD_TIM_CTL \ 3
6619 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
6620 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
6622 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
6627 CODE TOP_LCD \ LCD Sample
6628 \ \ if write : %xxxxWWWW --
6629 \ \ if read : -- %0000RRRR
6630 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6631 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6632 0= IF \ write LCD bits pattern
6634 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6635 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6638 THEN \ read LCD bits pattern
6641 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6642 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6647 CODE LCD_WRC \ char -- Write Char
6648 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6650 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
6651 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
6652 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6653 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6654 COLON \ high level word starts here
6655 TOP_LCD 2 20_US \ write high nibble first
6659 CODE LCD_WRF \ func -- Write Fonction
6660 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6664 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
6665 : LCD_HOME $02 LCD_WRF 100 20_us ;
6667 \ [UNDEFINED] OR [IF]
6669 \ \ https://forth-standard.org/standard/core/OR
6670 \ \ C OR x1 x2 -- x3 logical OR
6678 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
6679 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
6680 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
6681 \ : LCD_FN_SET $20 OR LCD_WrF ;
6682 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
6683 \ : LCD_GOTO $80 OR LCD_WrF ;
6686 \ CODE LCD_RDS \ -- status Read Status
6687 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6688 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6689 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6690 \ COLON \ starts a FORTH word
6691 \ TOP_LCD 2 20_us \ -- %0000HHHH
6692 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6693 \ HI2LO \ switch from FORTH to assembler
6694 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6695 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6696 \ MOV @RSP+,IP \ restore IP saved by COLON
6700 \ CODE LCD_RDC \ -- char Read Char
6701 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6706 \ ******************************\
6707 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6708 \ ******************************\
6709 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
6710 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
6711 BIT.B #SW2,&SW2_IN \ test switch S2
6712 0= IF \ case of switch S2 pressed
6713 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
6715 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
6718 BIT.B #SW1,&SW1_IN \ test switch S1 input
6719 0= IF \ case of Switch S1 pressed
6720 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
6722 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
6726 BW1 \ from quit on truncated RC5 message, repeated RC5 command
6730 \ ******************************\
6731 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6732 \ ******************************\
6733 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6734 \ ******************************\
6735 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6736 \ \ SMclock = 8|16|24 MHz
6737 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
6738 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
6739 \ \ SR(9)=new Toggle bit memory (ADD on)
6740 \ ******************************\
6741 \ RC5_FirstStartBitHalfCycle: \
6742 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
6743 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
6744 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
6745 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
6747 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
6748 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
6750 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
6751 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
6753 MOV #1778,X \ RC5_Period * 1us
6754 MOV #14,W \ count of loop
6756 \ ******************************\
6757 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
6758 \ ******************************\ |
6759 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
6760 \ RC5_Compute_3/4_Period: \ |
6761 RRUM #1,X \ X=1/2 cycle |
6764 ADD X,Y \ Y=3/4 cycle
6765 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
6767 \ ******************************\
6768 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
6769 \ ******************************\
6770 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6771 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
6772 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6773 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6774 SUB #1,W \ decrement count loop
6775 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
6776 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6777 0<> WHILE \ ----> out of loop ----+
6778 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6780 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
6781 CMP Y,X \ 1 | cycle time out of bound ?
6783 BIC #$30,&RC5_TIM_CTL \ | | stop timer
6784 GOTO BW1 \ | | quit on truncated RC5 message
6786 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
6788 REPEAT \ ----> loop back --+ | with X = new RC5_period value
6789 \ ******************************\ |
6790 \ RC5_SampleEndOf: \ <---------------------+
6791 \ ******************************\
6792 BIC #$30,&RC5_TIM_CTL \ stop timer
6793 \ ******************************\
6794 \ RC5_ComputeNewRC5word \
6795 \ ******************************\
6796 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
6797 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
6798 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
6799 \ ******************************\
6800 \ RC5_ComputeC6bit \
6801 \ ******************************\
6802 BIT #BIT14,T \ test /C6 bit in T
6803 0= IF BIS #BIT6,X \ set C6 bit in X
6804 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
6805 \ ******************************\
6806 \ RC5_CommandByteIsDone \ -- BASE RC5_code
6807 \ ******************************\
6808 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6809 \ ******************************\
6810 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
6811 XOR @RSP,T \ (new XOR old) Toggle bits
6812 BIT #UF10,T \ repeated RC5_command ?
6813 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
6814 XOR #UF10,0(RSP) \ 5 toggle bit memory
6815 \ ******************************\
6816 \ Display IR_RC5 code \
6817 \ ******************************\
6818 SUB #8,PSP \ TOS -- x x x x TOS
6819 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6820 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6821 MOV #$10,&BASEADR \ set hexadecimal base
6822 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6823 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6824 LO2HI \ switch from assembler to FORTH
6825 LCD_CLEAR \ set LCD cursor at home
6826 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6827 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
6828 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
6829 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
6830 HI2LO \ -- switch from FORTH to assembler
6831 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
6832 MOV @PSP+,TOS \ -- TOS
6836 \ ------------------------------\
6838 \ ------------------------------\
6840 \ ... \ insert here your background task
6843 CALL &RXON \ comment this line to disable TERMINAL
6845 \ ******************************\
6846 \ here start all interrupts \
6847 \ ******************************\
6848 \ here return all interrupts \
6849 \ ******************************\
6853 \ ------------------------------\
6854 CODE STOP \ stops multitasking, must to be used before downloading app
6855 \ ------------------------------\
6856 \ restore default action of primary DEFERred word SLEEP (assembly version)
6857 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
6858 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6859 MOV X,-2(X) \ restore the default background
6860 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
6861 ['] WARM >BODY IS WARM \ restore the default WARM
6863 ." RC5toLCD is removed. type START to restart"
6864 COLD \ performs reset to reset all interrupt vectors.
6867 \ ------------------------------\
6868 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
6869 \ ------------------------------\
6870 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
6871 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6872 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6873 \ -- \ID input divider \ 10 = /4
6874 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6875 \ - \TBCLR TimerB Clear
6878 \ -------------------------------\
6879 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6880 \ -- \CM Capture Mode
6885 \ --- \OUTMOD \ 011 = set/reset
6891 \ -------------------------------\
6893 \ -------------------------------\
6895 \ ------------------------------\
6896 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6897 \ ------------------------------\
6898 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6899 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6900 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6901 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6903 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6904 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6906 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6907 \ ------------------------------\
6908 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6909 \ ------------------------------\
6910 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6911 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6912 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6913 \ ------------------------------\
6914 BIS.B #LCDVo,&LCDVo_DIR \
6915 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6916 \ ------------------------------\
6917 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6918 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6919 \ ------------------------------\
6920 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6921 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6922 \ ******************************\
6924 \ ******************************\
6925 BIS.B #RC5,&IR_IE \ enable RC5_Int
6926 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6927 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6928 \ ******************************\
6929 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6930 \ ******************************\
6931 \ %01 0001 0100 \ TAxCTL
6932 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6933 \ -- \ ID divided by 1
6934 \ -- \ MC MODE = up to TAxCCRn
6935 \ - \ TACLR clear timer count
6938 \ ------------------------------\
6939 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6940 \ ------------------------------\
6942 \ --- \ TAIDEX pre divisor
6943 \ ------------------------------\
6944 \ %0000 0000 0000 0101 \ TAxCCR0
6945 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6946 \ ------------------------------\
6947 \ %0000 0000 0001 0000 \ TAxCCTL0
6948 \ - \ CAP capture/compare mode = compare
6951 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6952 \ ------------------------------\
6953 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6954 \ ------------------------------\
6955 \ define LPM mode for ACCEPT \
6956 \ ------------------------------\
6957 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6958 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6959 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6960 \ ------------------------------\
6962 \ ------------------------------\
6963 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
6964 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6965 \ ------------------------------\
6966 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6967 \ ------------------------------\
6968 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
6969 \ CMP #2,Y \ Power_ON event
6970 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
6972 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
6974 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
6976 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
6978 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
6979 \ ------------------------------\
6981 \ ------------------------------\
6983 \ ------------------------------\
6984 #1000 20_US \ 1- wait 20 ms
6985 %011 TOP_LCD \ 2- send DB5=DB4=1
6986 #205 20_US \ 3- wait 4,1 ms
6987 %011 TOP_LCD \ 4- send again DB5=DB4=1
6988 #5 20_US \ 5- wait 0,1 ms
6989 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6990 #2 20_US \ wait 40 us = LCD cycle
6991 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6992 #2 20_US \ wait 40 us = LCD cycle
6993 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6994 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6995 LCD_CLEAR \ 10- "LCD_Clear"
6996 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6997 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6998 LCD_CLEAR \ 10- "LCD_Clear"
6999 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7000 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7001 CR ." I love you" \ display message on LCD
7002 ['] CR >BODY IS CR \ CR executes its default value
7003 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
7004 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7005 ABORT \ ...and end APP_INIT with ABORT, no return.
7008 \ ------------------------------\
7009 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
7010 \ ------------------------------\
7011 MOV #SLEEP,X \ replace default background process
7012 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
7013 MOV #WARM,X \ replace default WARM
7014 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
7015 MOV X,PC \ then execute it
7018 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
7022 CODE 20_US \ n -- n * 20 us
7023 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7025 BIT #1,&LCD_TIM_CTL \ 3
7026 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7027 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7029 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7034 CODE TOP_LCD \ LCD Sample
7035 \ \ if write : %xxxxWWWW --
7036 \ \ if read : -- %0000RRRR
7037 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7038 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7039 0= IF \ write LCD bits pattern
7041 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7042 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7045 THEN \ read LCD bits pattern
7048 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7049 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7054 CODE LCD_WRC \ char -- Write Char
7055 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7057 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7058 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7059 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7060 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7061 COLON \ high level word starts here
7062 TOP_LCD 2 20_US \ write high nibble first
7066 CODE LCD_WRF \ func -- Write Fonction
7067 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7071 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7072 : LCD_HOME $02 LCD_WRF 100 20_us ;
7074 \ [UNDEFINED] OR [IF]
7076 \ \ https://forth-standard.org/standard/core/OR
7077 \ \ C OR x1 x2 -- x3 logical OR
7085 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7086 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7087 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7088 \ : LCD_FN_SET $20 OR LCD_WrF ;
7089 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7090 \ : LCD_GOTO $80 OR LCD_WrF ;
7093 \ CODE LCD_RDS \ -- status Read Status
7094 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7095 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7096 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7097 \ COLON \ starts a FORTH word
7098 \ TOP_LCD 2 20_us \ -- %0000HHHH
7099 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7100 \ HI2LO \ switch from FORTH to assembler
7101 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7102 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7103 \ MOV @RSP+,IP \ restore IP saved by COLON
7107 \ CODE LCD_RDC \ -- char Read Char
7108 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7113 \ ******************************\
7114 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7115 \ ******************************\
7116 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7117 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7118 BIT.B #SW2,&SW2_IN \ test switch S2
7119 0= IF \ case of switch S2 pressed
7120 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7122 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7125 BIT.B #SW1,&SW1_IN \ test switch S1 input
7126 0= IF \ case of Switch S1 pressed
7127 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7129 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7133 BW1 \ from quit on truncated RC5 message, repeated RC5 command
7137 \ ******************************\
7138 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7139 \ ******************************\
7140 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7141 \ ******************************\
7142 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7143 \ \ SMclock = 8|16|24 MHz
7144 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7145 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7146 \ \ SR(9)=new Toggle bit memory (ADD on)
7147 \ ******************************\
7148 \ RC5_FirstStartBitHalfCycle: \
7149 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7150 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7151 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
7152 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
7154 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
7155 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
7157 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
7158 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
7160 MOV #1778,X \ RC5_Period * 1us
7161 MOV #14,W \ count of loop
7163 \ ******************************\
7164 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
7165 \ ******************************\ |
7166 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7167 \ RC5_Compute_3/4_Period: \ |
7168 RRUM #1,X \ X=1/2 cycle |
7171 ADD X,Y \ Y=3/4 cycle
7172 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
7174 \ ******************************\
7175 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7176 \ ******************************\
7177 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7178 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
7179 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7180 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7181 SUB #1,W \ decrement count loop
7182 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
7183 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7184 0<> WHILE \ ----> out of loop ----+
7185 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7187 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
7188 CMP Y,X \ 1 | cycle time out of bound ?
7190 BIC #$30,&RC5_TIM_CTL \ | | stop timer
7191 GOTO BW1 \ | | quit on truncated RC5 message
7193 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
7195 REPEAT \ ----> loop back --+ | with X = new RC5_period value
7196 \ ******************************\ |
7197 \ RC5_SampleEndOf: \ <---------------------+
7198 \ ******************************\
7199 BIC #$30,&RC5_TIM_CTL \ stop timer
7200 \ ******************************\
7201 \ RC5_ComputeNewRC5word \
7202 \ ******************************\
7203 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
7204 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
7205 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
7206 \ ******************************\
7207 \ RC5_ComputeC6bit \
7208 \ ******************************\
7209 BIT #BIT14,T \ test /C6 bit in T
7210 0= IF BIS #BIT6,X \ set C6 bit in X
7211 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
7212 \ ******************************\
7213 \ RC5_CommandByteIsDone \ -- BASE RC5_code
7214 \ ******************************\
7215 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7216 \ ******************************\
7217 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
7218 XOR @RSP,T \ (new XOR old) Toggle bits
7219 BIT #UF10,T \ repeated RC5_command ?
7220 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
7221 XOR #UF10,0(RSP) \ 5 toggle bit memory
7222 \ ******************************\
7223 \ Display IR_RC5 code \
7224 \ ******************************\
7225 SUB #8,PSP \ TOS -- x x x x TOS
7226 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
7227 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
7228 MOV #$10,&BASEADR \ set hexadecimal base
7229 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
7230 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
7231 LO2HI \ switch from assembler to FORTH
7232 LCD_CLEAR \ set LCD cursor at home
7233 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
7234 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
7235 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
7236 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
7237 HI2LO \ -- switch from FORTH to assembler
7238 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
7239 MOV @PSP+,TOS \ -- TOS
7243 \ ------------------------------\
7245 \ ------------------------------\
7247 \ ... \ insert here your background task
7250 CALL &RXON \ comment this line to disable TERMINAL
7252 \ ******************************\
7253 \ here start all interrupts \
7254 \ ******************************\
7255 \ here return all interrupts \
7256 \ ******************************\
7260 \ ------------------------------\
7261 CODE STOP \ stops multitasking, must to be used before downloading app
7262 \ ------------------------------\
7263 \ restore default action of primary DEFERred word SLEEP (assembly version)
7264 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
7265 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
7266 MOV X,-2(X) \ restore the default background
7267 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
7268 ['] WARM >BODY IS WARM \ restore the default WARM
7270 ." RC5toLCD is removed. type START to restart"
7271 COLD \ performs reset to reset all interrupt vectors.
7274 \ ------------------------------\
7275 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
7276 \ ------------------------------\
7277 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
7278 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7279 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7280 \ -- \ID input divider \ 10 = /4
7281 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7282 \ - \TBCLR TimerB Clear
7285 \ -------------------------------\
7286 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7287 \ -- \CM Capture Mode
7292 \ --- \OUTMOD \ 011 = set/reset
7298 \ -------------------------------\
7300 \ -------------------------------\
7302 \ ------------------------------\
7303 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7304 \ ------------------------------\
7305 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7306 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7307 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
7308 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7310 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
7311 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
7313 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
7314 \ ------------------------------\
7315 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
7316 \ ------------------------------\
7317 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
7318 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
7319 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7320 \ ------------------------------\
7321 BIS.B #LCDVo,&LCDVo_DIR \
7322 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
7323 \ ------------------------------\
7324 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7325 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7326 \ ------------------------------\
7327 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7328 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7329 \ ******************************\
7331 \ ******************************\
7332 BIS.B #RC5,&IR_IE \ enable RC5_Int
7333 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7334 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7335 \ ******************************\
7336 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
7337 \ ******************************\
7338 \ %01 0001 0100 \ TAxCTL
7339 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
7340 \ -- \ ID divided by 1
7341 \ -- \ MC MODE = up to TAxCCRn
7342 \ - \ TACLR clear timer count
7345 \ ------------------------------\
7346 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
7347 \ ------------------------------\
7349 \ --- \ TAIDEX pre divisor
7350 \ ------------------------------\
7351 \ %0000 0000 0000 0101 \ TAxCCR0
7352 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
7353 \ ------------------------------\
7354 \ %0000 0000 0001 0000 \ TAxCCTL0
7355 \ - \ CAP capture/compare mode = compare
7358 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
7359 \ ------------------------------\
7360 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
7361 \ ------------------------------\
7362 \ define LPM mode for ACCEPT \
7363 \ ------------------------------\
7364 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7365 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7366 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7367 \ ------------------------------\
7369 \ ------------------------------\
7370 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
7371 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
7372 \ ------------------------------\
7373 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
7374 \ ------------------------------\
7375 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
7376 \ CMP #2,Y \ Power_ON event
7377 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
7379 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
7381 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
7383 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
7385 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
7386 \ ------------------------------\
7388 \ ------------------------------\
7390 \ ------------------------------\
7391 #1000 20_US \ 1- wait 20 ms
7392 %011 TOP_LCD \ 2- send DB5=DB4=1
7393 #205 20_US \ 3- wait 4,1 ms
7394 %011 TOP_LCD \ 4- send again DB5=DB4=1
7395 #5 20_US \ 5- wait 0,1 ms
7396 %011 TOP_LCD \ 6- send again again DB5=DB4=1
7397 #2 20_US \ wait 40 us = LCD cycle
7398 %010 TOP_LCD \ 7- send DB5=1 DB4=0
7399 #2 20_US \ wait 40 us = LCD cycle
7400 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7401 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7402 LCD_CLEAR \ 10- "LCD_Clear"
7403 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7404 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7405 LCD_CLEAR \ 10- "LCD_Clear"
7406 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7407 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7408 CR ." I love you" \ display message on LCD
7409 ['] CR >BODY IS CR \ CR executes its default value
7410 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
7411 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7412 ABORT \ ...and end APP_INIT with ABORT, no return.
7415 \ ------------------------------\
7416 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
7417 \ ------------------------------\
7418 MOV #SLEEP,X \ replace default background process
7419 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
7420 MOV #WARM,X \ replace default WARM
7421 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
7422 MOV X,PC \ then execute it
7425 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
7429 CODE 20_US \ n -- n * 20 us
7430 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7432 BIT #1,&LCD_TIM_CTL \ 3
7433 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7434 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7436 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7441 CODE TOP_LCD \ LCD Sample
7442 \ \ if write : %xxxxWWWW --
7443 \ \ if read : -- %0000RRRR
7444 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7445 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7446 0= IF \ write LCD bits pattern
7448 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7449 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7452 THEN \ read LCD bits pattern
7455 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7456 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7461 CODE LCD_WRC \ char -- Write Char
7462 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7464 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7465 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7466 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7467 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7468 COLON \ high level word starts here
7469 TOP_LCD 2 20_US \ write high nibble first
7473 CODE LCD_WRF \ func -- Write Fonction
7474 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7478 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7479 : LCD_HOME $02 LCD_WRF 100 20_us ;
7481 \ [UNDEFINED] OR [IF]
7483 \ \ https://forth-standard.org/standard/core/OR
7484 \ \ C OR x1 x2 -- x3 logical OR
7492 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7493 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7494 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7495 \ : LCD_FN_SET $20 OR LCD_WrF ;
7496 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7497 \ : LCD_GOTO $80 OR LCD_WrF ;
7500 \ CODE LCD_RDS \ -- status Read Status
7501 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7502 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7503 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7504 \ COLON \ starts a FORTH word
7505 \ TOP_LCD 2 20_us \ -- %0000HHHH
7506 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7507 \ HI2LO \ switch from FORTH to assembler
7508 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7509 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7510 \ MOV @RSP+,IP \ restore IP saved by COLON
7514 \ CODE LCD_RDC \ -- char Read Char
7515 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7520 \ ******************************\
7521 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7522 \ ******************************\
7523 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7524 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7525 BIT.B #SW2,&SW2_IN \ test switch S2
7526 0= IF \ case of switch S2 pressed
7527 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7529 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7532 BIT.B #SW1,&SW1_IN \ test switch S1 input
7533 0= IF \ case of Switch S1 pressed
7534 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7536 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7540 BW1 \ from quit on truncated RC5 message, repeated RC5 command
7544 \ ******************************\
7545 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7546 \ ******************************\
7547 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7548 \ ******************************\
7549 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7550 \ \ SMclock = 8|16|24 MHz
7551 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7552 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7553 \ \ SR(9)=new Toggle bit memory (ADD on)
7554 \ ******************************\
7555 \ RC5_FirstStartBitHalfCycle: \
7556 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7557 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7558 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
7559 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
7561 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
7562 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
7564 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
7565 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
7567 MOV #1778,X \ RC5_Period * 1us
7568 MOV #14,W \ count of loop
7570 \ ******************************\
7571 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
7572 \ ******************************\ |
7573 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7574 \ RC5_Compute_3/4_Period: \ |
7575 RRUM #1,X \ X=1/2 cycle |
7578 ADD X,Y \ Y=3/4 cycle
7579 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
7581 \ ******************************\
7582 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7583 \ ******************************\
7584 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7585 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
7586 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7587 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7588 SUB #1,W \ decrement count loop
7589 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
7590 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7591 0<> WHILE \ ----> out of loop ----+
7592 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7594 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
7595 CMP Y,X \ 1 | cycle time out of bound ?
7597 BIC #$30,&RC5_TIM_CTL \ | | stop timer
7598 GOTO BW1 \ | | quit on truncated RC5 message
7600 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
7602 REPEAT \ ----> loop back --+ | with X = new RC5_period value
7603 \ ******************************\ |
7604 \ RC5_SampleEndOf: \ <---------------------+
7605 \ ******************************\
7606 BIC #$30,&RC5_TIM_CTL \ stop timer
7607 \ ******************************\
7608 \ RC5_ComputeNewRC5word \
7609 \ ******************************\
7610 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
7611 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
7612 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
7613 \ ******************************\
7614 \ RC5_ComputeC6bit \
7615 \ ******************************\
7616 BIT #BIT14,T \ test /C6 bit in T
7617 0= IF BIS #BIT6,X \ set C6 bit in X
7618 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
7619 \ ******************************\
7620 \ RC5_CommandByteIsDone \ -- BASE RC5_code
7621 \ ******************************\
7622 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7623 \ ******************************\
7624 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
7625 XOR @RSP,T \ (new XOR old) Toggle bits
7626 BIT #UF10,T \ repeated RC5_command ?
7627 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
7628 XOR #UF10,0(RSP) \ 5 toggle bit memory
7629 \ ******************************\
7630 \ Display IR_RC5 code \
7631 \ ******************************\
7632 SUB #8,PSP \ TOS -- x x x x TOS
7633 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
7634 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
7635 MOV #$10,&BASEADR \ set hexadecimal base
7636 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
7637 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
7638 LO2HI \ switch from assembler to FORTH
7639 LCD_CLEAR \ set LCD cursor at home
7640 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
7641 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
7642 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
7643 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
7644 HI2LO \ -- switch from FORTH to assembler
7645 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
7646 MOV @PSP+,TOS \ -- TOS
7650 \ ------------------------------\
7652 \ ------------------------------\
7654 \ ... \ insert here your background task
7657 CALL &RXON \ comment this line to disable TERMINAL
7659 \ ******************************\
7660 \ here start all interrupts \
7661 \ ******************************\
7662 \ here return all interrupts \
7663 \ ******************************\
7667 \ ------------------------------\
7668 CODE STOP \ stops multitasking, must to be used before downloading app
7669 \ ------------------------------\
7670 \ restore default action of primary DEFERred word SLEEP (assembly version)
7671 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
7672 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
7673 MOV X,-2(X) \ restore the default background
7674 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
7675 ['] WARM >BODY IS WARM \ restore the default WARM
7677 ." RC5toLCD is removed. type START to restart"
7678 COLD \ performs reset to reset all interrupt vectors.
7681 \ ------------------------------\
7682 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
7683 \ ------------------------------\
7684 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
7685 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7686 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7687 \ -- \ID input divider \ 10 = /4
7688 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7689 \ - \TBCLR TimerB Clear
7692 \ -------------------------------\
7693 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7694 \ -- \CM Capture Mode
7699 \ --- \OUTMOD \ 011 = set/reset
7705 \ -------------------------------\
7707 \ -------------------------------\
7709 \ ------------------------------\
7710 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7711 \ ------------------------------\
7712 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7713 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7714 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
7715 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7717 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
7718 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
7720 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
7721 \ ------------------------------\
7722 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
7723 \ ------------------------------\
7724 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
7725 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
7726 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7727 \ ------------------------------\
7728 BIS.B #LCDVo,&LCDVo_DIR \
7729 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
7730 \ ------------------------------\
7731 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7732 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7733 \ ------------------------------\
7734 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7735 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7736 \ ******************************\
7738 \ ******************************\
7739 BIS.B #RC5,&IR_IE \ enable RC5_Int
7740 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7741 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7742 \ ******************************\
7743 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
7744 \ ******************************\
7745 \ %01 0001 0100 \ TAxCTL
7746 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
7747 \ -- \ ID divided by 1
7748 \ -- \ MC MODE = up to TAxCCRn
7749 \ - \ TACLR clear timer count
7752 \ ------------------------------\
7753 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
7754 \ ------------------------------\
7756 \ --- \ TAIDEX pre divisor
7757 \ ------------------------------\
7758 \ %0000 0000 0000 0101 \ TAxCCR0
7759 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
7760 \ ------------------------------\
7761 \ %0000 0000 0001 0000 \ TAxCCTL0
7762 \ - \ CAP capture/compare mode = compare
7765 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
7766 \ ------------------------------\
7767 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
7768 \ ------------------------------\
7769 \ define LPM mode for ACCEPT \
7770 \ ------------------------------\
7771 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7772 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7773 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7774 \ ------------------------------\
7776 \ ------------------------------\
7777 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
7778 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
7779 \ ------------------------------\
7780 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
7781 \ ------------------------------\
7782 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
7783 \ CMP #2,Y \ Power_ON event
7784 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
7786 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
7788 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
7790 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
7792 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
7793 \ ------------------------------\
7795 \ ------------------------------\
7797 \ ------------------------------\
7798 #1000 20_US \ 1- wait 20 ms
7799 %011 TOP_LCD \ 2- send DB5=DB4=1
7800 #205 20_US \ 3- wait 4,1 ms
7801 %011 TOP_LCD \ 4- send again DB5=DB4=1
7802 #5 20_US \ 5- wait 0,1 ms
7803 %011 TOP_LCD \ 6- send again again DB5=DB4=1
7804 #2 20_US \ wait 40 us = LCD cycle
7805 %010 TOP_LCD \ 7- send DB5=1 DB4=0
7806 #2 20_US \ wait 40 us = LCD cycle
7807 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7808 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7809 LCD_CLEAR \ 10- "LCD_Clear"
7810 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7811 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7812 LCD_CLEAR \ 10- "LCD_Clear"
7813 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7814 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7815 CR ." I love you" \ display message on LCD
7816 ['] CR >BODY IS CR \ CR executes its default value
7817 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
7818 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7819 ABORT \ ...and end APP_INIT with ABORT, no return.
7822 \ ------------------------------\
7823 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
7824 \ ------------------------------\
7825 MOV #SLEEP,X \ replace default background process
7826 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
7827 MOV #WARM,X \ replace default WARM
7828 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
7829 MOV X,PC \ then execute it
7832 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
7836 CODE 20_US \ n -- n * 20 us
7837 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7839 BIT #1,&LCD_TIM_CTL \ 3
7840 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7841 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7843 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7848 CODE TOP_LCD \ LCD Sample
7849 \ \ if write : %xxxxWWWW --
7850 \ \ if read : -- %0000RRRR
7851 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7852 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7853 0= IF \ write LCD bits pattern
7855 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7856 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7859 THEN \ read LCD bits pattern
7862 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7863 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7868 CODE LCD_WRC \ char -- Write Char
7869 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7871 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7872 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7873 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7874 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7875 COLON \ high level word starts here
7876 TOP_LCD 2 20_US \ write high nibble first
7880 CODE LCD_WRF \ func -- Write Fonction
7881 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7885 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7886 : LCD_HOME $02 LCD_WRF 100 20_us ;
7888 \ [UNDEFINED] OR [IF]
7890 \ \ https://forth-standard.org/standard/core/OR
7891 \ \ C OR x1 x2 -- x3 logical OR
7899 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7900 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7901 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7902 \ : LCD_FN_SET $20 OR LCD_WrF ;
7903 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7904 \ : LCD_GOTO $80 OR LCD_WrF ;
7907 \ CODE LCD_RDS \ -- status Read Status
7908 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7909 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7910 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7911 \ COLON \ starts a FORTH word
7912 \ TOP_LCD 2 20_us \ -- %0000HHHH
7913 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7914 \ HI2LO \ switch from FORTH to assembler
7915 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7916 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7917 \ MOV @RSP+,IP \ restore IP saved by COLON
7921 \ CODE LCD_RDC \ -- char Read Char
7922 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7927 \ ******************************\
7928 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7929 \ ******************************\
7930 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7931 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7932 BIT.B #SW2,&SW2_IN \ test switch S2
7933 0= IF \ case of switch S2 pressed
7934 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7936 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7939 BIT.B #SW1,&SW1_IN \ test switch S1 input
7940 0= IF \ case of Switch S1 pressed
7941 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7943 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7947 BW1 \ from quit on truncated RC5 message, repeated RC5 command
7951 \ ******************************\
7952 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7953 \ ******************************\
7954 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7955 \ ******************************\
7956 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7957 \ \ SMclock = 8|16|24 MHz
7958 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7959 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7960 \ \ SR(9)=new Toggle bit memory (ADD on)
7961 \ ******************************\
7962 \ RC5_FirstStartBitHalfCycle: \
7963 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7964 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7965 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
7966 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
7968 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
7969 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
7971 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
7972 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
7974 MOV #1778,X \ RC5_Period * 1us
7975 MOV #14,W \ count of loop
7977 \ ******************************\
7978 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
7979 \ ******************************\ |
7980 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7981 \ RC5_Compute_3/4_Period: \ |
7982 RRUM #1,X \ X=1/2 cycle |
7985 ADD X,Y \ Y=3/4 cycle
7986 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
7988 \ ******************************\
7989 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7990 \ ******************************\
7991 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7992 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
7993 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7994 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7995 SUB #1,W \ decrement count loop
7996 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
7997 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7998 0<> WHILE \ ----> out of loop ----+
7999 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8001 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
8002 CMP Y,X \ 1 | cycle time out of bound ?
8004 BIC #$30,&RC5_TIM_CTL \ | | stop timer
8005 GOTO BW1 \ | | quit on truncated RC5 message
8007 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
8009 REPEAT \ ----> loop back --+ | with X = new RC5_period value
8010 \ ******************************\ |
8011 \ RC5_SampleEndOf: \ <---------------------+
8012 \ ******************************\
8013 BIC #$30,&RC5_TIM_CTL \ stop timer
8014 \ ******************************\
8015 \ RC5_ComputeNewRC5word \
8016 \ ******************************\
8017 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
8018 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
8019 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
8020 \ ******************************\
8021 \ RC5_ComputeC6bit \
8022 \ ******************************\
8023 BIT #BIT14,T \ test /C6 bit in T
8024 0= IF BIS #BIT6,X \ set C6 bit in X
8025 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
8026 \ ******************************\
8027 \ RC5_CommandByteIsDone \ -- BASE RC5_code
8028 \ ******************************\
8029 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8030 \ ******************************\
8031 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
8032 XOR @RSP,T \ (new XOR old) Toggle bits
8033 BIT #UF10,T \ repeated RC5_command ?
8034 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
8035 XOR #UF10,0(RSP) \ 5 toggle bit memory
8036 \ ******************************\
8037 \ Display IR_RC5 code \
8038 \ ******************************\
8039 SUB #8,PSP \ TOS -- x x x x TOS
8040 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
8041 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
8042 MOV #$10,&BASEADR \ set hexadecimal base
8043 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
8044 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
8045 LO2HI \ switch from assembler to FORTH
8046 LCD_CLEAR \ set LCD cursor at home
8047 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
8048 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
8049 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
8050 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
8051 HI2LO \ -- switch from FORTH to assembler
8052 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
8053 MOV @PSP+,TOS \ -- TOS
8057 \ ------------------------------\
8059 \ ------------------------------\
8061 \ ... \ insert here your background task
8064 CALL &RXON \ comment this line to disable TERMINAL
8066 \ ******************************\
8067 \ here start all interrupts \
8068 \ ******************************\
8069 \ here return all interrupts \
8070 \ ******************************\
8074 \ ------------------------------\
8075 CODE STOP \ stops multitasking, must to be used before downloading app
8076 \ ------------------------------\
8077 \ restore default action of primary DEFERred word SLEEP (assembly version)
8078 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
8079 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
8080 MOV X,-2(X) \ restore the default background
8081 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
8082 ['] WARM >BODY IS WARM \ restore the default WARM
8084 ." RC5toLCD is removed. type START to restart"
8085 COLD \ performs reset to reset all interrupt vectors.
8088 \ ------------------------------\
8089 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
8090 \ ------------------------------\
8091 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
8092 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8093 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8094 \ -- \ID input divider \ 10 = /4
8095 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8096 \ - \TBCLR TimerB Clear
8099 \ -------------------------------\
8100 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8101 \ -- \CM Capture Mode
8106 \ --- \OUTMOD \ 011 = set/reset
8112 \ -------------------------------\
8114 \ -------------------------------\
8116 \ ------------------------------\
8117 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8118 \ ------------------------------\
8119 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8120 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8121 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
8122 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8124 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
8125 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8127 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8128 \ ------------------------------\
8129 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8130 \ ------------------------------\
8131 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8132 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8133 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8134 \ ------------------------------\
8135 BIS.B #LCDVo,&LCDVo_DIR \
8136 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8137 \ ------------------------------\
8138 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8139 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8140 \ ------------------------------\
8141 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8142 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8143 \ ******************************\
8145 \ ******************************\
8146 BIS.B #RC5,&IR_IE \ enable RC5_Int
8147 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8148 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8149 \ ******************************\
8150 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8151 \ ******************************\
8152 \ %01 0001 0100 \ TAxCTL
8153 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8154 \ -- \ ID divided by 1
8155 \ -- \ MC MODE = up to TAxCCRn
8156 \ - \ TACLR clear timer count
8159 \ ------------------------------\
8160 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8161 \ ------------------------------\
8163 \ --- \ TAIDEX pre divisor
8164 \ ------------------------------\
8165 \ %0000 0000 0000 0101 \ TAxCCR0
8166 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8167 \ ------------------------------\
8168 \ %0000 0000 0001 0000 \ TAxCCTL0
8169 \ - \ CAP capture/compare mode = compare
8172 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8173 \ ------------------------------\
8174 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8175 \ ------------------------------\
8176 \ define LPM mode for ACCEPT \
8177 \ ------------------------------\
8178 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8179 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8180 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8181 \ ------------------------------\
8183 \ ------------------------------\
8184 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
8185 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
8186 \ ------------------------------\
8187 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
8188 \ ------------------------------\
8189 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
8190 \ CMP #2,Y \ Power_ON event
8191 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
8193 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
8195 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
8197 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
8199 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
8200 \ ------------------------------\
8202 \ ------------------------------\
8204 \ ------------------------------\
8205 #1000 20_US \ 1- wait 20 ms
8206 %011 TOP_LCD \ 2- send DB5=DB4=1
8207 #205 20_US \ 3- wait 4,1 ms
8208 %011 TOP_LCD \ 4- send again DB5=DB4=1
8209 #5 20_US \ 5- wait 0,1 ms
8210 %011 TOP_LCD \ 6- send again again DB5=DB4=1
8211 #2 20_US \ wait 40 us = LCD cycle
8212 %010 TOP_LCD \ 7- send DB5=1 DB4=0
8213 #2 20_US \ wait 40 us = LCD cycle
8214 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8215 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8216 LCD_CLEAR \ 10- "LCD_Clear"
8217 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8218 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8219 LCD_CLEAR \ 10- "LCD_Clear"
8220 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8221 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8222 CR ." I love you" \ display message on LCD
8223 ['] CR >BODY IS CR \ CR executes its default value
8224 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
8225 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8226 ABORT \ ...and end APP_INIT with ABORT, no return.
8229 \ ------------------------------\
8230 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
8231 \ ------------------------------\
8232 MOV #SLEEP,X \ replace default background process
8233 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
8234 MOV #WARM,X \ replace default WARM
8235 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
8236 MOV X,PC \ then execute it
8239 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
8243 CODE 20_US \ n -- n * 20 us
8244 BEGIN \ here we presume that LCD_TIM_IFG = 1...
8246 BIT #1,&LCD_TIM_CTL \ 3
8247 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
8248 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
8250 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
8255 CODE TOP_LCD \ LCD Sample
8256 \ \ if write : %xxxxWWWW --
8257 \ \ if read : -- %0000RRRR
8258 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8259 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8260 0= IF \ write LCD bits pattern
8262 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8263 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8266 THEN \ read LCD bits pattern
8269 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8270 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8275 CODE LCD_WRC \ char -- Write Char
8276 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8278 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8279 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8280 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8281 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8282 COLON \ high level word starts here
8283 TOP_LCD 2 20_US \ write high nibble first
8287 CODE LCD_WRF \ func -- Write Fonction
8288 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8292 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
8293 : LCD_HOME $02 LCD_WRF 100 20_us ;
8295 \ [UNDEFINED] OR [IF]
8297 \ \ https://forth-standard.org/standard/core/OR
8298 \ \ C OR x1 x2 -- x3 logical OR
8306 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
8307 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
8308 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
8309 \ : LCD_FN_SET $20 OR LCD_WrF ;
8310 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
8311 \ : LCD_GOTO $80 OR LCD_WrF ;
8314 \ CODE LCD_RDS \ -- status Read Status
8315 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8316 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8317 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8318 \ COLON \ starts a FORTH word
8319 \ TOP_LCD 2 20_us \ -- %0000HHHH
8320 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8321 \ HI2LO \ switch from FORTH to assembler
8322 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8323 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8324 \ MOV @RSP+,IP \ restore IP saved by COLON
8328 \ CODE LCD_RDC \ -- char Read Char
8329 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8334 \ ******************************\
8335 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8336 \ ******************************\
8337 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
8338 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
8339 BIT.B #SW2,&SW2_IN \ test switch S2
8340 0= IF \ case of switch S2 pressed
8341 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
8343 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
8346 BIT.B #SW1,&SW1_IN \ test switch S1 input
8347 0= IF \ case of Switch S1 pressed
8348 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
8350 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
8354 BW1 \ from quit on truncated RC5 message, repeated RC5 command
8358 \ ******************************\
8359 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8360 \ ******************************\
8361 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8362 \ ******************************\
8363 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8364 \ \ SMclock = 8|16|24 MHz
8365 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
8366 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
8367 \ \ SR(9)=new Toggle bit memory (ADD on)
8368 \ ******************************\
8369 \ RC5_FirstStartBitHalfCycle: \
8370 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
8371 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
8372 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
8373 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
8375 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
8376 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
8378 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
8379 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
8381 MOV #1778,X \ RC5_Period * 1us
8382 MOV #14,W \ count of loop
8384 \ ******************************\
8385 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
8386 \ ******************************\ |
8387 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
8388 \ RC5_Compute_3/4_Period: \ |
8389 RRUM #1,X \ X=1/2 cycle |
8392 ADD X,Y \ Y=3/4 cycle
8393 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
8395 \ ******************************\
8396 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
8397 \ ******************************\
8398 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8399 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
8400 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8401 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8402 SUB #1,W \ decrement count loop
8403 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
8404 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8405 0<> WHILE \ ----> out of loop ----+
8406 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8408 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
8409 CMP Y,X \ 1 | cycle time out of bound ?
8411 BIC #$30,&RC5_TIM_CTL \ | | stop timer
8412 GOTO BW1 \ | | quit on truncated RC5 message
8414 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
8416 REPEAT \ ----> loop back --+ | with X = new RC5_period value
8417 \ ******************************\ |
8418 \ RC5_SampleEndOf: \ <---------------------+
8419 \ ******************************\
8420 BIC #$30,&RC5_TIM_CTL \ stop timer
8421 \ ******************************\
8422 \ RC5_ComputeNewRC5word \
8423 \ ******************************\
8424 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
8425 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
8426 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
8427 \ ******************************\
8428 \ RC5_ComputeC6bit \
8429 \ ******************************\
8430 BIT #BIT14,T \ test /C6 bit in T
8431 0= IF BIS #BIT6,X \ set C6 bit in X
8432 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
8433 \ ******************************\
8434 \ RC5_CommandByteIsDone \ -- BASE RC5_code
8435 \ ******************************\
8436 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8437 \ ******************************\
8438 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
8439 XOR @RSP,T \ (new XOR old) Toggle bits
8440 BIT #UF10,T \ repeated RC5_command ?
8441 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
8442 XOR #UF10,0(RSP) \ 5 toggle bit memory
8443 \ ******************************\
8444 \ Display IR_RC5 code \
8445 \ ******************************\
8446 SUB #8,PSP \ TOS -- x x x x TOS
8447 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
8448 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
8449 MOV #$10,&BASEADR \ set hexadecimal base
8450 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
8451 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
8452 LO2HI \ switch from assembler to FORTH
8453 LCD_CLEAR \ set LCD cursor at home
8454 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
8455 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
8456 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
8457 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
8458 HI2LO \ -- switch from FORTH to assembler
8459 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
8460 MOV @PSP+,TOS \ -- TOS
8464 \ ------------------------------\
8466 \ ------------------------------\
8468 \ ... \ insert here your background task
8471 CALL &RXON \ comment this line to disable TERMINAL
8473 \ ******************************\
8474 \ here start all interrupts \
8475 \ ******************************\
8476 \ here return all interrupts \
8477 \ ******************************\
8481 \ ------------------------------\
8482 CODE STOP \ stops multitasking, must to be used before downloading app
8483 \ ------------------------------\
8484 \ restore default action of primary DEFERred word SLEEP (assembly version)
8485 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
8486 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
8487 MOV X,-2(X) \ restore the default background
8488 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
8489 ['] WARM >BODY IS WARM \ restore the default WARM
8491 ." RC5toLCD is removed. type START to restart"
8492 COLD \ performs reset to reset all interrupt vectors.
8495 \ ------------------------------\
8496 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
8497 \ ------------------------------\
8498 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
8499 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8500 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8501 \ -- \ID input divider \ 10 = /4
8502 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8503 \ - \TBCLR TimerB Clear
8506 \ -------------------------------\
8507 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8508 \ -- \CM Capture Mode
8513 \ --- \OUTMOD \ 011 = set/reset
8519 \ -------------------------------\
8521 \ -------------------------------\
8523 \ ------------------------------\
8524 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8525 \ ------------------------------\
8526 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8527 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8528 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
8529 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8531 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
8532 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8534 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8535 \ ------------------------------\
8536 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8537 \ ------------------------------\
8538 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8539 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8540 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8541 \ ------------------------------\
8542 BIS.B #LCDVo,&LCDVo_DIR \
8543 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8544 \ ------------------------------\
8545 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8546 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8547 \ ------------------------------\
8548 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8549 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8550 \ ******************************\
8552 \ ******************************\
8553 BIS.B #RC5,&IR_IE \ enable RC5_Int
8554 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8555 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8556 \ ******************************\
8557 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8558 \ ******************************\
8559 \ %01 0001 0100 \ TAxCTL
8560 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8561 \ -- \ ID divided by 1
8562 \ -- \ MC MODE = up to TAxCCRn
8563 \ - \ TACLR clear timer count
8566 \ ------------------------------\
8567 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8568 \ ------------------------------\
8570 \ --- \ TAIDEX pre divisor
8571 \ ------------------------------\
8572 \ %0000 0000 0000 0101 \ TAxCCR0
8573 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8574 \ ------------------------------\
8575 \ %0000 0000 0001 0000 \ TAxCCTL0
8576 \ - \ CAP capture/compare mode = compare
8579 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8580 \ ------------------------------\
8581 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8582 \ ------------------------------\
8583 \ define LPM mode for ACCEPT \
8584 \ ------------------------------\
8585 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8586 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8587 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8588 \ ------------------------------\
8590 \ ------------------------------\
8591 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
8592 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
8593 \ ------------------------------\
8594 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
8595 \ ------------------------------\
8596 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
8597 \ CMP #2,Y \ Power_ON event
8598 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
8600 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
8602 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
8604 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
8606 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
8607 \ ------------------------------\
8609 \ ------------------------------\
8611 \ ------------------------------\
8612 #1000 20_US \ 1- wait 20 ms
8613 %011 TOP_LCD \ 2- send DB5=DB4=1
8614 #205 20_US \ 3- wait 4,1 ms
8615 %011 TOP_LCD \ 4- send again DB5=DB4=1
8616 #5 20_US \ 5- wait 0,1 ms
8617 %011 TOP_LCD \ 6- send again again DB5=DB4=1
8618 #2 20_US \ wait 40 us = LCD cycle
8619 %010 TOP_LCD \ 7- send DB5=1 DB4=0
8620 #2 20_US \ wait 40 us = LCD cycle
8621 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8622 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8623 LCD_CLEAR \ 10- "LCD_Clear"
8624 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8625 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8626 LCD_CLEAR \ 10- "LCD_Clear"
8627 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8628 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8629 CR ." I love you" \ display message on LCD
8630 ['] CR >BODY IS CR \ CR executes its default value
8631 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
8632 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8633 ABORT \ ...and end APP_INIT with ABORT, no return.
8636 \ ------------------------------\
8637 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
8638 \ ------------------------------\
8639 MOV #SLEEP,X \ replace default background process
8640 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
8641 MOV #WARM,X \ replace default WARM
8642 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
8643 MOV X,PC \ then execute it
8646 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
8650 CODE 20_US \ n -- n * 20 us
8651 BEGIN \ here we presume that LCD_TIM_IFG = 1...
8653 BIT #1,&LCD_TIM_CTL \ 3
8654 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
8655 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
8657 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
8662 CODE TOP_LCD \ LCD Sample
8663 \ \ if write : %xxxxWWWW --
8664 \ \ if read : -- %0000RRRR
8665 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8666 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8667 0= IF \ write LCD bits pattern
8669 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8670 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8673 THEN \ read LCD bits pattern
8676 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8677 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8682 CODE LCD_WRC \ char -- Write Char
8683 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8685 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8686 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8687 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8688 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8689 COLON \ high level word starts here
8690 TOP_LCD 2 20_US \ write high nibble first
8694 CODE LCD_WRF \ func -- Write Fonction
8695 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8699 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
8700 : LCD_HOME $02 LCD_WRF 100 20_us ;
8702 \ [UNDEFINED] OR [IF]
8704 \ \ https://forth-standard.org/standard/core/OR
8705 \ \ C OR x1 x2 -- x3 logical OR
8713 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
8714 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
8715 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
8716 \ : LCD_FN_SET $20 OR LCD_WrF ;
8717 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
8718 \ : LCD_GOTO $80 OR LCD_WrF ;
8721 \ CODE LCD_RDS \ -- status Read Status
8722 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8723 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8724 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8725 \ COLON \ starts a FORTH word
8726 \ TOP_LCD 2 20_us \ -- %0000HHHH
8727 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8728 \ HI2LO \ switch from FORTH to assembler
8729 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8730 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8731 \ MOV @RSP+,IP \ restore IP saved by COLON
8735 \ CODE LCD_RDC \ -- char Read Char
8736 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8741 \ ******************************\
8742 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8743 \ ******************************\
8744 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
8745 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
8746 BIT.B #SW2,&SW2_IN \ test switch S2
8747 0= IF \ case of switch S2 pressed
8748 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
8750 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
8753 BIT.B #SW1,&SW1_IN \ test switch S1 input
8754 0= IF \ case of Switch S1 pressed
8755 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
8757 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
8761 BW1 \ from quit on truncated RC5 message, repeated RC5 command
8765 \ ******************************\
8766 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8767 \ ******************************\
8768 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8769 \ ******************************\
8770 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8771 \ \ SMclock = 8|16|24 MHz
8772 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
8773 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
8774 \ \ SR(9)=new Toggle bit memory (ADD on)
8775 \ ******************************\
8776 \ RC5_FirstStartBitHalfCycle: \
8777 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
8778 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
8779 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
8780 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
8782 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
8783 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
8785 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
8786 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
8788 MOV #1778,X \ RC5_Period * 1us
8789 MOV #14,W \ count of loop
8791 \ ******************************\
8792 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
8793 \ ******************************\ |
8794 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
8795 \ RC5_Compute_3/4_Period: \ |
8796 RRUM #1,X \ X=1/2 cycle |
8799 ADD X,Y \ Y=3/4 cycle
8800 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
8802 \ ******************************\
8803 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
8804 \ ******************************\
8805 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8806 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
8807 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8808 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8809 SUB #1,W \ decrement count loop
8810 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
8811 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8812 0<> WHILE \ ----> out of loop ----+
8813 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8815 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
8816 CMP Y,X \ 1 | cycle time out of bound ?
8818 BIC #$30,&RC5_TIM_CTL \ | | stop timer
8819 GOTO BW1 \ | | quit on truncated RC5 message
8821 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
8823 REPEAT \ ----> loop back --+ | with X = new RC5_period value
8824 \ ******************************\ |
8825 \ RC5_SampleEndOf: \ <---------------------+
8826 \ ******************************\
8827 BIC #$30,&RC5_TIM_CTL \ stop timer
8828 \ ******************************\
8829 \ RC5_ComputeNewRC5word \
8830 \ ******************************\
8831 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
8832 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
8833 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
8834 \ ******************************\
8835 \ RC5_ComputeC6bit \
8836 \ ******************************\
8837 BIT #BIT14,T \ test /C6 bit in T
8838 0= IF BIS #BIT6,X \ set C6 bit in X
8839 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
8840 \ ******************************\
8841 \ RC5_CommandByteIsDone \ -- BASE RC5_code
8842 \ ******************************\
8843 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8844 \ ******************************\
8845 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
8846 XOR @RSP,T \ (new XOR old) Toggle bits
8847 BIT #UF10,T \ repeated RC5_command ?
8848 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
8849 XOR #UF10,0(RSP) \ 5 toggle bit memory
8850 \ ******************************\
8851 \ Display IR_RC5 code \
8852 \ ******************************\
8853 SUB #8,PSP \ TOS -- x x x x TOS
8854 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
8855 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
8856 MOV #$10,&BASEADR \ set hexadecimal base
8857 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
8858 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
8859 LO2HI \ switch from assembler to FORTH
8860 LCD_CLEAR \ set LCD cursor at home
8861 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
8862 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
8863 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
8864 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
8865 HI2LO \ -- switch from FORTH to assembler
8866 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
8867 MOV @PSP+,TOS \ -- TOS
8871 \ ------------------------------\
8873 \ ------------------------------\
8875 \ ... \ insert here your background task
8878 CALL &RXON \ comment this line to disable TERMINAL
8880 \ ******************************\
8881 \ here start all interrupts \
8882 \ ******************************\
8883 \ here return all interrupts \
8884 \ ******************************\
8888 \ ------------------------------\
8889 CODE STOP \ stops multitasking, must to be used before downloading app
8890 \ ------------------------------\
8891 \ restore default action of primary DEFERred word SLEEP (assembly version)
8892 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
8893 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
8894 MOV X,-2(X) \ restore the default background
8895 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
8896 ['] WARM >BODY IS WARM \ restore the default WARM
8898 ." RC5toLCD is removed. type START to restart"
8899 COLD \ performs reset to reset all interrupt vectors.
8902 \ ------------------------------\
8903 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
8904 \ ------------------------------\
8905 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
8906 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8907 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8908 \ -- \ID input divider \ 10 = /4
8909 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8910 \ - \TBCLR TimerB Clear
8913 \ -------------------------------\
8914 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8915 \ -- \CM Capture Mode
8920 \ --- \OUTMOD \ 011 = set/reset
8926 \ -------------------------------\
8928 \ -------------------------------\
8930 \ ------------------------------\
8931 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8932 \ ------------------------------\
8933 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8934 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8935 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
8936 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8938 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
8939 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8941 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8942 \ ------------------------------\
8943 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8944 \ ------------------------------\
8945 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8946 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8947 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8948 \ ------------------------------\
8949 BIS.B #LCDVo,&LCDVo_DIR \
8950 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8951 \ ------------------------------\
8952 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8953 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8954 \ ------------------------------\
8955 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8956 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8957 \ ******************************\
8959 \ ******************************\
8960 BIS.B #RC5,&IR_IE \ enable RC5_Int
8961 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8962 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8963 \ ******************************\
8964 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8965 \ ******************************\
8966 \ %01 0001 0100 \ TAxCTL
8967 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8968 \ -- \ ID divided by 1
8969 \ -- \ MC MODE = up to TAxCCRn
8970 \ - \ TACLR clear timer count
8973 \ ------------------------------\
8974 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8975 \ ------------------------------\
8977 \ --- \ TAIDEX pre divisor
8978 \ ------------------------------\
8979 \ %0000 0000 0000 0101 \ TAxCCR0
8980 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8981 \ ------------------------------\
8982 \ %0000 0000 0001 0000 \ TAxCCTL0
8983 \ - \ CAP capture/compare mode = compare
8986 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8987 \ ------------------------------\
8988 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8989 \ ------------------------------\
8990 \ define LPM mode for ACCEPT \
8991 \ ------------------------------\
8992 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8993 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8994 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8995 \ ------------------------------\
8997 \ ------------------------------\
8998 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
8999 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9000 \ ------------------------------\
9001 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9002 \ ------------------------------\
9003 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
9004 \ CMP #2,Y \ Power_ON event
9005 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9007 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
9009 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9011 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9013 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9014 \ ------------------------------\
9016 \ ------------------------------\
9018 \ ------------------------------\
9019 #1000 20_US \ 1- wait 20 ms
9020 %011 TOP_LCD \ 2- send DB5=DB4=1
9021 #205 20_US \ 3- wait 4,1 ms
9022 %011 TOP_LCD \ 4- send again DB5=DB4=1
9023 #5 20_US \ 5- wait 0,1 ms
9024 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9025 #2 20_US \ wait 40 us = LCD cycle
9026 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9027 #2 20_US \ wait 40 us = LCD cycle
9028 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9029 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9030 LCD_CLEAR \ 10- "LCD_Clear"
9031 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9032 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9033 LCD_CLEAR \ 10- "LCD_Clear"
9034 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9035 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9036 CR ." I love you" \ display message on LCD
9037 ['] CR >BODY IS CR \ CR executes its default value
9038 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9039 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9040 ABORT \ ...and end APP_INIT with ABORT, no return.
9043 \ ------------------------------\
9044 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
9045 \ ------------------------------\
9046 MOV #SLEEP,X \ replace default background process
9047 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
9048 MOV #WARM,X \ replace default WARM
9049 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
9050 MOV X,PC \ then execute it
9053 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9057 CODE 20_US \ n -- n * 20 us
9058 BEGIN \ here we presume that LCD_TIM_IFG = 1...
9060 BIT #1,&LCD_TIM_CTL \ 3
9061 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
9062 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
9064 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
9069 CODE TOP_LCD \ LCD Sample
9070 \ \ if write : %xxxxWWWW --
9071 \ \ if read : -- %0000RRRR
9072 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9073 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9074 0= IF \ write LCD bits pattern
9076 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9077 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9080 THEN \ read LCD bits pattern
9083 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9084 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9089 CODE LCD_WRC \ char -- Write Char
9090 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9092 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9093 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9094 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9095 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9096 COLON \ high level word starts here
9097 TOP_LCD 2 20_US \ write high nibble first
9101 CODE LCD_WRF \ func -- Write Fonction
9102 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9106 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
9107 : LCD_HOME $02 LCD_WRF 100 20_us ;
9109 \ [UNDEFINED] OR [IF]
9111 \ \ https://forth-standard.org/standard/core/OR
9112 \ \ C OR x1 x2 -- x3 logical OR
9120 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
9121 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
9122 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
9123 \ : LCD_FN_SET $20 OR LCD_WrF ;
9124 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
9125 \ : LCD_GOTO $80 OR LCD_WrF ;
9128 \ CODE LCD_RDS \ -- status Read Status
9129 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9130 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9131 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9132 \ COLON \ starts a FORTH word
9133 \ TOP_LCD 2 20_us \ -- %0000HHHH
9134 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9135 \ HI2LO \ switch from FORTH to assembler
9136 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9137 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9138 \ MOV @RSP+,IP \ restore IP saved by COLON
9142 \ CODE LCD_RDC \ -- char Read Char
9143 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9148 \ ******************************\
9149 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9150 \ ******************************\
9151 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9152 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9153 BIT.B #SW2,&SW2_IN \ test switch S2
9154 0= IF \ case of switch S2 pressed
9155 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9157 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9160 BIT.B #SW1,&SW1_IN \ test switch S1 input
9161 0= IF \ case of Switch S1 pressed
9162 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9164 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9168 BW1 \ from quit on truncated RC5 message, repeated RC5 command
9172 \ ******************************\
9173 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9174 \ ******************************\
9175 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9176 \ ******************************\
9177 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9178 \ \ SMclock = 8|16|24 MHz
9179 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9180 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9181 \ \ SR(9)=new Toggle bit memory (ADD on)
9182 \ ******************************\
9183 \ RC5_FirstStartBitHalfCycle: \
9184 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9185 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9186 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
9187 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
9189 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
9190 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
9192 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
9193 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
9195 MOV #1778,X \ RC5_Period * 1us
9196 MOV #14,W \ count of loop
9198 \ ******************************\
9199 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
9200 \ ******************************\ |
9201 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9202 \ RC5_Compute_3/4_Period: \ |
9203 RRUM #1,X \ X=1/2 cycle |
9206 ADD X,Y \ Y=3/4 cycle
9207 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
9209 \ ******************************\
9210 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9211 \ ******************************\
9212 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9213 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
9214 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9215 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9216 SUB #1,W \ decrement count loop
9217 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
9218 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9219 0<> WHILE \ ----> out of loop ----+
9220 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9222 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
9223 CMP Y,X \ 1 | cycle time out of bound ?
9225 BIC #$30,&RC5_TIM_CTL \ | | stop timer
9226 GOTO BW1 \ | | quit on truncated RC5 message
9228 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
9230 REPEAT \ ----> loop back --+ | with X = new RC5_period value
9231 \ ******************************\ |
9232 \ RC5_SampleEndOf: \ <---------------------+
9233 \ ******************************\
9234 BIC #$30,&RC5_TIM_CTL \ stop timer
9235 \ ******************************\
9236 \ RC5_ComputeNewRC5word \
9237 \ ******************************\
9238 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
9239 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
9240 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
9241 \ ******************************\
9242 \ RC5_ComputeC6bit \
9243 \ ******************************\
9244 BIT #BIT14,T \ test /C6 bit in T
9245 0= IF BIS #BIT6,X \ set C6 bit in X
9246 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
9247 \ ******************************\
9248 \ RC5_CommandByteIsDone \ -- BASE RC5_code
9249 \ ******************************\
9250 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9251 \ ******************************\
9252 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
9253 XOR @RSP,T \ (new XOR old) Toggle bits
9254 BIT #UF10,T \ repeated RC5_command ?
9255 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
9256 XOR #UF10,0(RSP) \ 5 toggle bit memory
9257 \ ******************************\
9258 \ Display IR_RC5 code \
9259 \ ******************************\
9260 SUB #8,PSP \ TOS -- x x x x TOS
9261 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
9262 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
9263 MOV #$10,&BASEADR \ set hexadecimal base
9264 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
9265 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
9266 LO2HI \ switch from assembler to FORTH
9267 LCD_CLEAR \ set LCD cursor at home
9268 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
9269 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
9270 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
9271 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
9272 HI2LO \ -- switch from FORTH to assembler
9273 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
9274 MOV @PSP+,TOS \ -- TOS
9278 \ ------------------------------\
9280 \ ------------------------------\
9282 \ ... \ insert here your background task
9285 CALL &RXON \ comment this line to disable TERMINAL
9287 \ ******************************\
9288 \ here start all interrupts \
9289 \ ******************************\
9290 \ here return all interrupts \
9291 \ ******************************\
9295 \ ------------------------------\
9296 CODE STOP \ stops multitasking, must to be used before downloading app
9297 \ ------------------------------\
9298 \ restore default action of primary DEFERred word SLEEP (assembly version)
9299 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
9300 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
9301 MOV X,-2(X) \ restore the default background
9302 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
9303 ['] WARM >BODY IS WARM \ restore the default WARM
9305 ." RC5toLCD is removed. type START to restart"
9306 COLD \ performs reset to reset all interrupt vectors.
9309 \ ------------------------------\
9310 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
9311 \ ------------------------------\
9312 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
9313 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9314 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9315 \ -- \ID input divider \ 10 = /4
9316 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9317 \ - \TBCLR TimerB Clear
9320 \ -------------------------------\
9321 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9322 \ -- \CM Capture Mode
9327 \ --- \OUTMOD \ 011 = set/reset
9333 \ -------------------------------\
9335 \ -------------------------------\
9337 \ ------------------------------\
9338 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9339 \ ------------------------------\
9340 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9341 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9342 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
9343 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9345 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
9346 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9348 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
9349 \ ------------------------------\
9350 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9351 \ ------------------------------\
9352 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
9353 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9354 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9355 \ ------------------------------\
9356 BIS.B #LCDVo,&LCDVo_DIR \
9357 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
9358 \ ------------------------------\
9359 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9360 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9361 \ ------------------------------\
9362 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9363 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9364 \ ******************************\
9366 \ ******************************\
9367 BIS.B #RC5,&IR_IE \ enable RC5_Int
9368 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9369 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9370 \ ******************************\
9371 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9372 \ ******************************\
9373 \ %01 0001 0100 \ TAxCTL
9374 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
9375 \ -- \ ID divided by 1
9376 \ -- \ MC MODE = up to TAxCCRn
9377 \ - \ TACLR clear timer count
9380 \ ------------------------------\
9381 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
9382 \ ------------------------------\
9384 \ --- \ TAIDEX pre divisor
9385 \ ------------------------------\
9386 \ %0000 0000 0000 0101 \ TAxCCR0
9387 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9388 \ ------------------------------\
9389 \ %0000 0000 0001 0000 \ TAxCCTL0
9390 \ - \ CAP capture/compare mode = compare
9393 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
9394 \ ------------------------------\
9395 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9396 \ ------------------------------\
9397 \ define LPM mode for ACCEPT \
9398 \ ------------------------------\
9399 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9400 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9401 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9402 \ ------------------------------\
9404 \ ------------------------------\
9405 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
9406 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9407 \ ------------------------------\
9408 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9409 \ ------------------------------\
9410 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
9411 \ CMP #2,Y \ Power_ON event
9412 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9414 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
9416 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9418 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9420 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9421 \ ------------------------------\
9423 \ ------------------------------\
9425 \ ------------------------------\
9426 #1000 20_US \ 1- wait 20 ms
9427 %011 TOP_LCD \ 2- send DB5=DB4=1
9428 #205 20_US \ 3- wait 4,1 ms
9429 %011 TOP_LCD \ 4- send again DB5=DB4=1
9430 #5 20_US \ 5- wait 0,1 ms
9431 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9432 #2 20_US \ wait 40 us = LCD cycle
9433 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9434 #2 20_US \ wait 40 us = LCD cycle
9435 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9436 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9437 LCD_CLEAR \ 10- "LCD_Clear"
9438 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9439 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9440 LCD_CLEAR \ 10- "LCD_Clear"
9441 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9442 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9443 CR ." I love you" \ display message on LCD
9444 ['] CR >BODY IS CR \ CR executes its default value
9445 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9446 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9447 ABORT \ ...and end APP_INIT with ABORT, no return.
9450 \ ------------------------------\
9451 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
9452 \ ------------------------------\
9453 MOV #SLEEP,X \ replace default background process
9454 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
9455 MOV #WARM,X \ replace default WARM
9456 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
9457 MOV X,PC \ then execute it
9460 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9464 CODE 20_US \ n -- n * 20 us
9465 BEGIN \ here we presume that LCD_TIM_IFG = 1...
9467 BIT #1,&LCD_TIM_CTL \ 3
9468 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
9469 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
9471 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
9476 CODE TOP_LCD \ LCD Sample
9477 \ \ if write : %xxxxWWWW --
9478 \ \ if read : -- %0000RRRR
9479 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9480 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9481 0= IF \ write LCD bits pattern
9483 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9484 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9487 THEN \ read LCD bits pattern
9490 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9491 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9496 CODE LCD_WRC \ char -- Write Char
9497 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9499 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9500 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9501 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9502 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9503 COLON \ high level word starts here
9504 TOP_LCD 2 20_US \ write high nibble first
9508 CODE LCD_WRF \ func -- Write Fonction
9509 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9513 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
9514 : LCD_HOME $02 LCD_WRF 100 20_us ;
9516 \ [UNDEFINED] OR [IF]
9518 \ \ https://forth-standard.org/standard/core/OR
9519 \ \ C OR x1 x2 -- x3 logical OR
9527 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
9528 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
9529 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
9530 \ : LCD_FN_SET $20 OR LCD_WrF ;
9531 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
9532 \ : LCD_GOTO $80 OR LCD_WrF ;
9535 \ CODE LCD_RDS \ -- status Read Status
9536 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9537 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9538 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9539 \ COLON \ starts a FORTH word
9540 \ TOP_LCD 2 20_us \ -- %0000HHHH
9541 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9542 \ HI2LO \ switch from FORTH to assembler
9543 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9544 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9545 \ MOV @RSP+,IP \ restore IP saved by COLON
9549 \ CODE LCD_RDC \ -- char Read Char
9550 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9555 \ ******************************\
9556 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9557 \ ******************************\
9558 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9559 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9560 BIT.B #SW2,&SW2_IN \ test switch S2
9561 0= IF \ case of switch S2 pressed
9562 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9564 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9567 BIT.B #SW1,&SW1_IN \ test switch S1 input
9568 0= IF \ case of Switch S1 pressed
9569 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9571 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9575 BW1 \ from quit on truncated RC5 message, repeated RC5 command
9579 \ ******************************\
9580 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9581 \ ******************************\
9582 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9583 \ ******************************\
9584 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9585 \ \ SMclock = 8|16|24 MHz
9586 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9587 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9588 \ \ SR(9)=new Toggle bit memory (ADD on)
9589 \ ******************************\
9590 \ RC5_FirstStartBitHalfCycle: \
9591 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9592 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9593 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
9594 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
9596 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
9597 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
9599 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
9600 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
9602 MOV #1778,X \ RC5_Period * 1us
9603 MOV #14,W \ count of loop
9605 \ ******************************\
9606 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
9607 \ ******************************\ |
9608 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9609 \ RC5_Compute_3/4_Period: \ |
9610 RRUM #1,X \ X=1/2 cycle |
9613 ADD X,Y \ Y=3/4 cycle
9614 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
9616 \ ******************************\
9617 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9618 \ ******************************\
9619 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9620 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
9621 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9622 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9623 SUB #1,W \ decrement count loop
9624 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
9625 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9626 0<> WHILE \ ----> out of loop ----+
9627 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9629 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
9630 CMP Y,X \ 1 | cycle time out of bound ?
9632 BIC #$30,&RC5_TIM_CTL \ | | stop timer
9633 GOTO BW1 \ | | quit on truncated RC5 message
9635 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
9637 REPEAT \ ----> loop back --+ | with X = new RC5_period value
9638 \ ******************************\ |
9639 \ RC5_SampleEndOf: \ <---------------------+
9640 \ ******************************\
9641 BIC #$30,&RC5_TIM_CTL \ stop timer
9642 \ ******************************\
9643 \ RC5_ComputeNewRC5word \
9644 \ ******************************\
9645 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
9646 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
9647 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
9648 \ ******************************\
9649 \ RC5_ComputeC6bit \
9650 \ ******************************\
9651 BIT #BIT14,T \ test /C6 bit in T
9652 0= IF BIS #BIT6,X \ set C6 bit in X
9653 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
9654 \ ******************************\
9655 \ RC5_CommandByteIsDone \ -- BASE RC5_code
9656 \ ******************************\
9657 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9658 \ ******************************\
9659 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
9660 XOR @RSP,T \ (new XOR old) Toggle bits
9661 BIT #UF10,T \ repeated RC5_command ?
9662 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
9663 XOR #UF10,0(RSP) \ 5 toggle bit memory
9664 \ ******************************\
9665 \ Display IR_RC5 code \
9666 \ ******************************\
9667 SUB #8,PSP \ TOS -- x x x x TOS
9668 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
9669 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
9670 MOV #$10,&BASEADR \ set hexadecimal base
9671 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
9672 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
9673 LO2HI \ switch from assembler to FORTH
9674 LCD_CLEAR \ set LCD cursor at home
9675 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
9676 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
9677 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
9678 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
9679 HI2LO \ -- switch from FORTH to assembler
9680 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
9681 MOV @PSP+,TOS \ -- TOS
9685 \ ------------------------------\
9687 \ ------------------------------\
9689 \ ... \ insert here your background task
9692 CALL &RXON \ comment this line to disable TERMINAL
9694 \ ******************************\
9695 \ here start all interrupts \
9696 \ ******************************\
9697 \ here return all interrupts \
9698 \ ******************************\
9702 \ ------------------------------\
9703 CODE STOP \ stops multitasking, must to be used before downloading app
9704 \ ------------------------------\
9705 \ restore default action of primary DEFERred word SLEEP (assembly version)
9706 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
9707 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
9708 MOV X,-2(X) \ restore the default background
9709 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
9710 ['] WARM >BODY IS WARM \ restore the default WARM
9712 ." RC5toLCD is removed. type START to restart"
9713 COLD \ performs reset to reset all interrupt vectors.
9716 \ ------------------------------\
9717 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
9718 \ ------------------------------\
9719 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
9720 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9721 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9722 \ -- \ID input divider \ 10 = /4
9723 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9724 \ - \TBCLR TimerB Clear
9727 \ -------------------------------\
9728 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9729 \ -- \CM Capture Mode
9734 \ --- \OUTMOD \ 011 = set/reset
9740 \ -------------------------------\
9742 \ -------------------------------\
9744 \ ------------------------------\
9745 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9746 \ ------------------------------\
9747 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9748 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9749 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
9750 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9752 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
9753 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9755 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
9756 \ ------------------------------\
9757 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9758 \ ------------------------------\
9759 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
9760 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9761 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9762 \ ------------------------------\
9763 BIS.B #LCDVo,&LCDVo_DIR \
9764 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
9765 \ ------------------------------\
9766 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9767 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9768 \ ------------------------------\
9769 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9770 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9771 \ ******************************\
9773 \ ******************************\
9774 BIS.B #RC5,&IR_IE \ enable RC5_Int
9775 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9776 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9777 \ ******************************\
9778 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9779 \ ******************************\
9780 \ %01 0001 0100 \ TAxCTL
9781 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
9782 \ -- \ ID divided by 1
9783 \ -- \ MC MODE = up to TAxCCRn
9784 \ - \ TACLR clear timer count
9787 \ ------------------------------\
9788 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
9789 \ ------------------------------\
9791 \ --- \ TAIDEX pre divisor
9792 \ ------------------------------\
9793 \ %0000 0000 0000 0101 \ TAxCCR0
9794 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9795 \ ------------------------------\
9796 \ %0000 0000 0001 0000 \ TAxCCTL0
9797 \ - \ CAP capture/compare mode = compare
9800 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
9801 \ ------------------------------\
9802 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9803 \ ------------------------------\
9804 \ define LPM mode for ACCEPT \
9805 \ ------------------------------\
9806 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9807 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9808 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9809 \ ------------------------------\
9811 \ ------------------------------\
9812 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
9813 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9814 \ ------------------------------\
9815 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9816 \ ------------------------------\
9817 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
9818 \ CMP #2,Y \ Power_ON event
9819 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9821 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
9823 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9825 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9827 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9828 \ ------------------------------\
9830 \ ------------------------------\
9832 \ ------------------------------\
9833 #1000 20_US \ 1- wait 20 ms
9834 %011 TOP_LCD \ 2- send DB5=DB4=1
9835 #205 20_US \ 3- wait 4,1 ms
9836 %011 TOP_LCD \ 4- send again DB5=DB4=1
9837 #5 20_US \ 5- wait 0,1 ms
9838 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9839 #2 20_US \ wait 40 us = LCD cycle
9840 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9841 #2 20_US \ wait 40 us = LCD cycle
9842 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9843 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9844 LCD_CLEAR \ 10- "LCD_Clear"
9845 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9846 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9847 LCD_CLEAR \ 10- "LCD_Clear"
9848 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9849 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9850 CR ." I love you" \ display message on LCD
9851 ['] CR >BODY IS CR \ CR executes its default value
9852 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9853 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9854 ABORT \ ...and end APP_INIT with ABORT, no return.
9857 \ ------------------------------\
9858 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
9859 \ ------------------------------\
9860 MOV #SLEEP,X \ replace default background process
9861 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
9862 MOV #WARM,X \ replace default WARM
9863 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
9864 MOV X,PC \ then execute it
9867 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9871 CODE 20_US \ n -- n * 20 us
9872 BEGIN \ here we presume that LCD_TIM_IFG = 1...
9874 BIT #1,&LCD_TIM_CTL \ 3
9875 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
9876 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
9878 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
9883 CODE TOP_LCD \ LCD Sample
9884 \ \ if write : %xxxxWWWW --
9885 \ \ if read : -- %0000RRRR
9886 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9887 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9888 0= IF \ write LCD bits pattern
9890 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9891 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9894 THEN \ read LCD bits pattern
9897 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9898 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9903 CODE LCD_WRC \ char -- Write Char
9904 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9906 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9907 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9908 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9909 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9910 COLON \ high level word starts here
9911 TOP_LCD 2 20_US \ write high nibble first
9915 CODE LCD_WRF \ func -- Write Fonction
9916 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9920 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
9921 : LCD_HOME $02 LCD_WRF 100 20_us ;
9923 \ [UNDEFINED] OR [IF]
9925 \ \ https://forth-standard.org/standard/core/OR
9926 \ \ C OR x1 x2 -- x3 logical OR
9934 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
9935 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
9936 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
9937 \ : LCD_FN_SET $20 OR LCD_WrF ;
9938 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
9939 \ : LCD_GOTO $80 OR LCD_WrF ;
9942 \ CODE LCD_RDS \ -- status Read Status
9943 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9944 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9945 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9946 \ COLON \ starts a FORTH word
9947 \ TOP_LCD 2 20_us \ -- %0000HHHH
9948 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9949 \ HI2LO \ switch from FORTH to assembler
9950 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9951 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9952 \ MOV @RSP+,IP \ restore IP saved by COLON
9956 \ CODE LCD_RDC \ -- char Read Char
9957 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9962 \ ******************************\
9963 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9964 \ ******************************\
9965 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9966 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9967 BIT.B #SW2,&SW2_IN \ test switch S2
9968 0= IF \ case of switch S2 pressed
9969 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9971 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9974 BIT.B #SW1,&SW1_IN \ test switch S1 input
9975 0= IF \ case of Switch S1 pressed
9976 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9978 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9982 BW1 \ from quit on truncated RC5 message, repeated RC5 command
9986 \ ******************************\
9987 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9988 \ ******************************\
9989 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9990 \ ******************************\
9991 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9992 \ \ SMclock = 8|16|24 MHz
9993 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9994 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9995 \ \ SR(9)=new Toggle bit memory (ADD on)
9996 \ ******************************\
9997 \ RC5_FirstStartBitHalfCycle: \
9998 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9999 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10000 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10001 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10003 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10004 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10006 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10007 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10009 MOV #1778,X \ RC5_Period * 1us
10010 MOV #14,W \ count of loop
10012 \ ******************************\
10013 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10014 \ ******************************\ |
10015 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10016 \ RC5_Compute_3/4_Period: \ |
10017 RRUM #1,X \ X=1/2 cycle |
10020 ADD X,Y \ Y=3/4 cycle
10021 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10023 \ ******************************\
10024 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10025 \ ******************************\
10026 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10027 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10028 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10029 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10030 SUB #1,W \ decrement count loop
10031 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10032 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10033 0<> WHILE \ ----> out of loop ----+
10034 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10036 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10037 CMP Y,X \ 1 | cycle time out of bound ?
10038 U>= IF \ 2 ^ | yes:
10039 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10040 GOTO BW1 \ | | quit on truncated RC5 message
10042 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10044 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10045 \ ******************************\ |
10046 \ RC5_SampleEndOf: \ <---------------------+
10047 \ ******************************\
10048 BIC #$30,&RC5_TIM_CTL \ stop timer
10049 \ ******************************\
10050 \ RC5_ComputeNewRC5word \
10051 \ ******************************\
10052 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10053 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10054 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10055 \ ******************************\
10056 \ RC5_ComputeC6bit \
10057 \ ******************************\
10058 BIT #BIT14,T \ test /C6 bit in T
10059 0= IF BIS #BIT6,X \ set C6 bit in X
10060 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10061 \ ******************************\
10062 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10063 \ ******************************\
10064 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10065 \ ******************************\
10066 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10067 XOR @RSP,T \ (new XOR old) Toggle bits
10068 BIT #UF10,T \ repeated RC5_command ?
10069 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
10070 XOR #UF10,0(RSP) \ 5 toggle bit memory
10071 \ ******************************\
10072 \ Display IR_RC5 code \
10073 \ ******************************\
10074 SUB #8,PSP \ TOS -- x x x x TOS
10075 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10076 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10077 MOV #$10,&BASEADR \ set hexadecimal base
10078 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10079 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10080 LO2HI \ switch from assembler to FORTH
10081 LCD_CLEAR \ set LCD cursor at home
10082 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10083 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10084 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10085 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10086 HI2LO \ -- switch from FORTH to assembler
10087 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10088 MOV @PSP+,TOS \ -- TOS
10092 \ ------------------------------\
10094 \ ------------------------------\
10096 \ ... \ insert here your background task
10099 CALL &RXON \ comment this line to disable TERMINAL
10101 \ ******************************\
10102 \ here start all interrupts \
10103 \ ******************************\
10104 \ here return all interrupts \
10105 \ ******************************\
10109 \ ------------------------------\
10110 CODE STOP \ stops multitasking, must to be used before downloading app
10111 \ ------------------------------\
10112 \ restore default action of primary DEFERred word SLEEP (assembly version)
10113 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
10114 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
10115 MOV X,-2(X) \ restore the default background
10116 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
10117 ['] WARM >BODY IS WARM \ restore the default WARM
10119 ." RC5toLCD is removed. type START to restart"
10120 COLD \ performs reset to reset all interrupt vectors.
10123 \ ------------------------------\
10124 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
10125 \ ------------------------------\
10126 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
10127 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10128 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10129 \ -- \ID input divider \ 10 = /4
10130 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10131 \ - \TBCLR TimerB Clear
10134 \ -------------------------------\
10135 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10136 \ -- \CM Capture Mode
10141 \ --- \OUTMOD \ 011 = set/reset
10147 \ -------------------------------\
10149 \ -------------------------------\
10151 \ ------------------------------\
10152 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10153 \ ------------------------------\
10154 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10155 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10156 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
10157 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10159 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
10160 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10162 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
10163 \ ------------------------------\
10164 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10165 \ ------------------------------\
10166 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
10167 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10168 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10169 \ ------------------------------\
10170 BIS.B #LCDVo,&LCDVo_DIR \
10171 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
10172 \ ------------------------------\
10173 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10174 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10175 \ ------------------------------\
10176 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10177 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10178 \ ******************************\
10180 \ ******************************\
10181 BIS.B #RC5,&IR_IE \ enable RC5_Int
10182 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10183 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10184 \ ******************************\
10185 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
10186 \ ******************************\
10187 \ %01 0001 0100 \ TAxCTL
10188 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
10189 \ -- \ ID divided by 1
10190 \ -- \ MC MODE = up to TAxCCRn
10191 \ - \ TACLR clear timer count
10194 \ ------------------------------\
10195 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
10196 \ ------------------------------\
10198 \ --- \ TAIDEX pre divisor
10199 \ ------------------------------\
10200 \ %0000 0000 0000 0101 \ TAxCCR0
10201 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
10202 \ ------------------------------\
10203 \ %0000 0000 0001 0000 \ TAxCCTL0
10204 \ - \ CAP capture/compare mode = compare
10207 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
10208 \ ------------------------------\
10209 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
10210 \ ------------------------------\
10211 \ define LPM mode for ACCEPT \
10212 \ ------------------------------\
10213 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10214 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10215 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10216 \ ------------------------------\
10218 \ ------------------------------\
10219 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
10220 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
10221 \ ------------------------------\
10222 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
10223 \ ------------------------------\
10224 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
10225 \ CMP #2,Y \ Power_ON event
10226 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
10228 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
10230 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
10232 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
10234 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
10235 \ ------------------------------\
10237 \ ------------------------------\
10239 \ ------------------------------\
10240 #1000 20_US \ 1- wait 20 ms
10241 %011 TOP_LCD \ 2- send DB5=DB4=1
10242 #205 20_US \ 3- wait 4,1 ms
10243 %011 TOP_LCD \ 4- send again DB5=DB4=1
10244 #5 20_US \ 5- wait 0,1 ms
10245 %011 TOP_LCD \ 6- send again again DB5=DB4=1
10246 #2 20_US \ wait 40 us = LCD cycle
10247 %010 TOP_LCD \ 7- send DB5=1 DB4=0
10248 #2 20_US \ wait 40 us = LCD cycle
10249 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10250 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10251 LCD_CLEAR \ 10- "LCD_Clear"
10252 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10253 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10254 LCD_CLEAR \ 10- "LCD_Clear"
10255 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10256 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10257 CR ." I love you" \ display message on LCD
10258 ['] CR >BODY IS CR \ CR executes its default value
10259 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
10260 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
10261 ABORT \ ...and end APP_INIT with ABORT, no return.
10264 \ ------------------------------\
10265 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
10266 \ ------------------------------\
10267 MOV #SLEEP,X \ replace default background process
10268 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
10269 MOV #WARM,X \ replace default WARM
10270 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
10271 MOV X,PC \ then execute it
10274 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
10278 CODE 20_US \ n -- n * 20 us
10279 BEGIN \ here we presume that LCD_TIM_IFG = 1...
10281 BIT #1,&LCD_TIM_CTL \ 3
10282 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
10283 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
10285 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
10290 CODE TOP_LCD \ LCD Sample
10291 \ \ if write : %xxxxWWWW --
10292 \ \ if read : -- %0000RRRR
10293 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10294 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10295 0= IF \ write LCD bits pattern
10296 AND.B #LCD_DB,TOS \
10297 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10298 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10301 THEN \ read LCD bits pattern
10304 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10305 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10306 AND.B #LCD_DB,TOS \
10310 CODE LCD_WRC \ char -- Write Char
10311 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10313 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10314 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10315 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10316 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10317 COLON \ high level word starts here
10318 TOP_LCD 2 20_US \ write high nibble first
10322 CODE LCD_WRF \ func -- Write Fonction
10323 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10327 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
10328 : LCD_HOME $02 LCD_WRF 100 20_us ;
10330 \ [UNDEFINED] OR [IF]
10332 \ \ https://forth-standard.org/standard/core/OR
10333 \ \ C OR x1 x2 -- x3 logical OR
10341 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
10342 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
10343 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
10344 \ : LCD_FN_SET $20 OR LCD_WrF ;
10345 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
10346 \ : LCD_GOTO $80 OR LCD_WrF ;
10349 \ CODE LCD_RDS \ -- status Read Status
10350 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10351 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10352 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10353 \ COLON \ starts a FORTH word
10354 \ TOP_LCD 2 20_us \ -- %0000HHHH
10355 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
10356 \ HI2LO \ switch from FORTH to assembler
10357 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
10358 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
10359 \ MOV @RSP+,IP \ restore IP saved by COLON
10363 \ CODE LCD_RDC \ -- char Read Char
10364 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10369 \ ******************************\
10370 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10371 \ ******************************\
10372 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10373 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
10374 BIT.B #SW2,&SW2_IN \ test switch S2
10375 0= IF \ case of switch S2 pressed
10376 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10378 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
10381 BIT.B #SW1,&SW1_IN \ test switch S1 input
10382 0= IF \ case of Switch S1 pressed
10383 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10385 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10389 BW1 \ from quit on truncated RC5 message, repeated RC5 command
10393 \ ******************************\
10394 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10395 \ ******************************\
10396 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10397 \ ******************************\
10398 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10399 \ \ SMclock = 8|16|24 MHz
10400 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10401 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10402 \ \ SR(9)=new Toggle bit memory (ADD on)
10403 \ ******************************\
10404 \ RC5_FirstStartBitHalfCycle: \
10405 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10406 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10407 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10408 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10410 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10411 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10413 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10414 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10416 MOV #1778,X \ RC5_Period * 1us
10417 MOV #14,W \ count of loop
10419 \ ******************************\
10420 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10421 \ ******************************\ |
10422 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10423 \ RC5_Compute_3/4_Period: \ |
10424 RRUM #1,X \ X=1/2 cycle |
10427 ADD X,Y \ Y=3/4 cycle
10428 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10430 \ ******************************\
10431 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10432 \ ******************************\
10433 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10434 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10435 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10436 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10437 SUB #1,W \ decrement count loop
10438 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10439 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10440 0<> WHILE \ ----> out of loop ----+
10441 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10443 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10444 CMP Y,X \ 1 | cycle time out of bound ?
10445 U>= IF \ 2 ^ | yes:
10446 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10447 GOTO BW1 \ | | quit on truncated RC5 message
10449 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10451 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10452 \ ******************************\ |
10453 \ RC5_SampleEndOf: \ <---------------------+
10454 \ ******************************\
10455 BIC #$30,&RC5_TIM_CTL \ stop timer
10456 \ ******************************\
10457 \ RC5_ComputeNewRC5word \
10458 \ ******************************\
10459 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10460 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10461 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10462 \ ******************************\
10463 \ RC5_ComputeC6bit \
10464 \ ******************************\
10465 BIT #BIT14,T \ test /C6 bit in T
10466 0= IF BIS #BIT6,X \ set C6 bit in X
10467 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10468 \ ******************************\
10469 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10470 \ ******************************\
10471 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10472 \ ******************************\
10473 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10474 XOR @RSP,T \ (new XOR old) Toggle bits
10475 BIT #UF10,T \ repeated RC5_command ?
10476 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
10477 XOR #UF10,0(RSP) \ 5 toggle bit memory
10478 \ ******************************\
10479 \ Display IR_RC5 code \
10480 \ ******************************\
10481 SUB #8,PSP \ TOS -- x x x x TOS
10482 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10483 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10484 MOV #$10,&BASEADR \ set hexadecimal base
10485 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10486 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10487 LO2HI \ switch from assembler to FORTH
10488 LCD_CLEAR \ set LCD cursor at home
10489 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10490 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10491 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10492 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10493 HI2LO \ -- switch from FORTH to assembler
10494 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10495 MOV @PSP+,TOS \ -- TOS
10499 \ ------------------------------\
10501 \ ------------------------------\
10503 \ ... \ insert here your background task
10506 CALL &RXON \ comment this line to disable TERMINAL
10508 \ ******************************\
10509 \ here start all interrupts \
10510 \ ******************************\
10511 \ here return all interrupts \
10512 \ ******************************\
10516 \ ------------------------------\
10517 CODE STOP \ stops multitasking, must to be used before downloading app
10518 \ ------------------------------\
10519 \ restore default action of primary DEFERred word SLEEP (assembly version)
10520 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
10521 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
10522 MOV X,-2(X) \ restore the default background
10523 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
10524 ['] WARM >BODY IS WARM \ restore the default WARM
10526 ." RC5toLCD is removed. type START to restart"
10527 COLD \ performs reset to reset all interrupt vectors.
10530 \ ------------------------------\
10531 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
10532 \ ------------------------------\
10533 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
10534 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10535 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10536 \ -- \ID input divider \ 10 = /4
10537 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10538 \ - \TBCLR TimerB Clear
10541 \ -------------------------------\
10542 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10543 \ -- \CM Capture Mode
10548 \ --- \OUTMOD \ 011 = set/reset
10554 \ -------------------------------\
10556 \ -------------------------------\
10558 \ ------------------------------\
10559 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10560 \ ------------------------------\
10561 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10562 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10563 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
10564 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10566 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
10567 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10569 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
10570 \ ------------------------------\
10571 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10572 \ ------------------------------\
10573 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
10574 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10575 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10576 \ ------------------------------\
10577 BIS.B #LCDVo,&LCDVo_DIR \
10578 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
10579 \ ------------------------------\
10580 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10581 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10582 \ ------------------------------\
10583 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10584 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10585 \ ******************************\
10587 \ ******************************\
10588 BIS.B #RC5,&IR_IE \ enable RC5_Int
10589 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10590 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10591 \ ******************************\
10592 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
10593 \ ******************************\
10594 \ %01 0001 0100 \ TAxCTL
10595 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
10596 \ -- \ ID divided by 1
10597 \ -- \ MC MODE = up to TAxCCRn
10598 \ - \ TACLR clear timer count
10601 \ ------------------------------\
10602 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
10603 \ ------------------------------\
10605 \ --- \ TAIDEX pre divisor
10606 \ ------------------------------\
10607 \ %0000 0000 0000 0101 \ TAxCCR0
10608 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
10609 \ ------------------------------\
10610 \ %0000 0000 0001 0000 \ TAxCCTL0
10611 \ - \ CAP capture/compare mode = compare
10614 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
10615 \ ------------------------------\
10616 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
10617 \ ------------------------------\
10618 \ define LPM mode for ACCEPT \
10619 \ ------------------------------\
10620 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10621 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10622 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10623 \ ------------------------------\
10625 \ ------------------------------\
10626 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
10627 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
10628 \ ------------------------------\
10629 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
10630 \ ------------------------------\
10631 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
10632 \ CMP #2,Y \ Power_ON event
10633 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
10635 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
10637 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
10639 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
10641 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
10642 \ ------------------------------\
10644 \ ------------------------------\
10646 \ ------------------------------\
10647 #1000 20_US \ 1- wait 20 ms
10648 %011 TOP_LCD \ 2- send DB5=DB4=1
10649 #205 20_US \ 3- wait 4,1 ms
10650 %011 TOP_LCD \ 4- send again DB5=DB4=1
10651 #5 20_US \ 5- wait 0,1 ms
10652 %011 TOP_LCD \ 6- send again again DB5=DB4=1
10653 #2 20_US \ wait 40 us = LCD cycle
10654 %010 TOP_LCD \ 7- send DB5=1 DB4=0
10655 #2 20_US \ wait 40 us = LCD cycle
10656 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10657 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10658 LCD_CLEAR \ 10- "LCD_Clear"
10659 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10660 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10661 LCD_CLEAR \ 10- "LCD_Clear"
10662 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10663 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10664 CR ." I love you" \ display message on LCD
10665 ['] CR >BODY IS CR \ CR executes its default value
10666 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
10667 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
10668 ABORT \ ...and end APP_INIT with ABORT, no return.
10671 \ ------------------------------\
10672 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
10673 \ ------------------------------\
10674 MOV #SLEEP,X \ replace default background process
10675 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
10676 MOV #WARM,X \ replace default WARM
10677 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
10678 MOV X,PC \ then execute it
10681 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
10685 CODE 20_US \ n -- n * 20 us
10686 BEGIN \ here we presume that LCD_TIM_IFG = 1...
10688 BIT #1,&LCD_TIM_CTL \ 3
10689 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
10690 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
10692 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
10697 CODE TOP_LCD \ LCD Sample
10698 \ \ if write : %xxxxWWWW --
10699 \ \ if read : -- %0000RRRR
10700 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10701 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10702 0= IF \ write LCD bits pattern
10703 AND.B #LCD_DB,TOS \
10704 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10705 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10708 THEN \ read LCD bits pattern
10711 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10712 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10713 AND.B #LCD_DB,TOS \
10717 CODE LCD_WRC \ char -- Write Char
10718 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10720 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10721 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10722 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10723 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10724 COLON \ high level word starts here
10725 TOP_LCD 2 20_US \ write high nibble first
10729 CODE LCD_WRF \ func -- Write Fonction
10730 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10734 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
10735 : LCD_HOME $02 LCD_WRF 100 20_us ;
10737 \ [UNDEFINED] OR [IF]
10739 \ \ https://forth-standard.org/standard/core/OR
10740 \ \ C OR x1 x2 -- x3 logical OR
10748 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
10749 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
10750 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
10751 \ : LCD_FN_SET $20 OR LCD_WrF ;
10752 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
10753 \ : LCD_GOTO $80 OR LCD_WrF ;
10756 \ CODE LCD_RDS \ -- status Read Status
10757 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10758 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10759 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10760 \ COLON \ starts a FORTH word
10761 \ TOP_LCD 2 20_us \ -- %0000HHHH
10762 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
10763 \ HI2LO \ switch from FORTH to assembler
10764 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
10765 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
10766 \ MOV @RSP+,IP \ restore IP saved by COLON
10770 \ CODE LCD_RDC \ -- char Read Char
10771 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10776 \ ******************************\
10777 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10778 \ ******************************\
10779 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10780 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
10781 BIT.B #SW2,&SW2_IN \ test switch S2
10782 0= IF \ case of switch S2 pressed
10783 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10785 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
10788 BIT.B #SW1,&SW1_IN \ test switch S1 input
10789 0= IF \ case of Switch S1 pressed
10790 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10792 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10796 BW1 \ from quit on truncated RC5 message, repeated RC5 command
10800 \ ******************************\
10801 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10802 \ ******************************\
10803 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10804 \ ******************************\
10805 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10806 \ \ SMclock = 8|16|24 MHz
10807 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10808 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10809 \ \ SR(9)=new Toggle bit memory (ADD on)
10810 \ ******************************\
10811 \ RC5_FirstStartBitHalfCycle: \
10812 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10813 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10814 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10815 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10817 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10818 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10820 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10821 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10823 MOV #1778,X \ RC5_Period * 1us
10824 MOV #14,W \ count of loop
10826 \ ******************************\
10827 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10828 \ ******************************\ |
10829 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10830 \ RC5_Compute_3/4_Period: \ |
10831 RRUM #1,X \ X=1/2 cycle |
10834 ADD X,Y \ Y=3/4 cycle
10835 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10837 \ ******************************\
10838 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10839 \ ******************************\
10840 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10841 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10842 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10843 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10844 SUB #1,W \ decrement count loop
10845 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10846 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10847 0<> WHILE \ ----> out of loop ----+
10848 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10850 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10851 CMP Y,X \ 1 | cycle time out of bound ?
10852 U>= IF \ 2 ^ | yes:
10853 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10854 GOTO BW1 \ | | quit on truncated RC5 message
10856 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10858 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10859 \ ******************************\ |
10860 \ RC5_SampleEndOf: \ <---------------------+
10861 \ ******************************\
10862 BIC #$30,&RC5_TIM_CTL \ stop timer
10863 \ ******************************\
10864 \ RC5_ComputeNewRC5word \
10865 \ ******************************\
10866 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10867 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10868 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10869 \ ******************************\
10870 \ RC5_ComputeC6bit \
10871 \ ******************************\
10872 BIT #BIT14,T \ test /C6 bit in T
10873 0= IF BIS #BIT6,X \ set C6 bit in X
10874 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10875 \ ******************************\
10876 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10877 \ ******************************\
10878 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10879 \ ******************************\
10880 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10881 XOR @RSP,T \ (new XOR old) Toggle bits
10882 BIT #UF10,T \ repeated RC5_command ?
10883 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
10884 XOR #UF10,0(RSP) \ 5 toggle bit memory
10885 \ ******************************\
10886 \ Display IR_RC5 code \
10887 \ ******************************\
10888 SUB #8,PSP \ TOS -- x x x x TOS
10889 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10890 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10891 MOV #$10,&BASEADR \ set hexadecimal base
10892 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10893 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10894 LO2HI \ switch from assembler to FORTH
10895 LCD_CLEAR \ set LCD cursor at home
10896 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10897 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10898 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10899 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10900 HI2LO \ -- switch from FORTH to assembler
10901 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10902 MOV @PSP+,TOS \ -- TOS
10906 \ ------------------------------\
10908 \ ------------------------------\
10910 \ ... \ insert here your background task
10913 CALL &RXON \ comment this line to disable TERMINAL
10915 \ ******************************\
10916 \ here start all interrupts \
10917 \ ******************************\
10918 \ here return all interrupts \
10919 \ ******************************\
10923 \ ------------------------------\
10924 CODE STOP \ stops multitasking, must to be used before downloading app
10925 \ ------------------------------\
10926 \ restore default action of primary DEFERred word SLEEP (assembly version)
10927 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
10928 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
10929 MOV X,-2(X) \ restore the default background
10930 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
10931 ['] WARM >BODY IS WARM \ restore the default WARM
10933 ." RC5toLCD is removed. type START to restart"
10934 COLD \ performs reset to reset all interrupt vectors.
10937 \ ------------------------------\
10938 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
10939 \ ------------------------------\
10940 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
10941 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10942 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10943 \ -- \ID input divider \ 10 = /4
10944 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10945 \ - \TBCLR TimerB Clear
10948 \ -------------------------------\
10949 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10950 \ -- \CM Capture Mode
10955 \ --- \OUTMOD \ 011 = set/reset
10961 \ -------------------------------\
10963 \ -------------------------------\
10965 \ ------------------------------\
10966 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10967 \ ------------------------------\
10968 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10969 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10970 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
10971 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10973 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
10974 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10976 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
10977 \ ------------------------------\
10978 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10979 \ ------------------------------\
10980 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
10981 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10982 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10983 \ ------------------------------\
10984 BIS.B #LCDVo,&LCDVo_DIR \
10985 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
10986 \ ------------------------------\
10987 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10988 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10989 \ ------------------------------\
10990 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10991 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10992 \ ******************************\
10994 \ ******************************\
10995 BIS.B #RC5,&IR_IE \ enable RC5_Int
10996 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10997 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10998 \ ******************************\
10999 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11000 \ ******************************\
11001 \ %01 0001 0100 \ TAxCTL
11002 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
11003 \ -- \ ID divided by 1
11004 \ -- \ MC MODE = up to TAxCCRn
11005 \ - \ TACLR clear timer count
11008 \ ------------------------------\
11009 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
11010 \ ------------------------------\
11012 \ --- \ TAIDEX pre divisor
11013 \ ------------------------------\
11014 \ %0000 0000 0000 0101 \ TAxCCR0
11015 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11016 \ ------------------------------\
11017 \ %0000 0000 0001 0000 \ TAxCCTL0
11018 \ - \ CAP capture/compare mode = compare
11021 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
11022 \ ------------------------------\
11023 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11024 \ ------------------------------\
11025 \ define LPM mode for ACCEPT \
11026 \ ------------------------------\
11027 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11028 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11029 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11030 \ ------------------------------\
11032 \ ------------------------------\
11033 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
11034 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11035 \ ------------------------------\
11036 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11037 \ ------------------------------\
11038 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
11039 \ CMP #2,Y \ Power_ON event
11040 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11042 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
11044 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11046 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11048 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11049 \ ------------------------------\
11051 \ ------------------------------\
11053 \ ------------------------------\
11054 #1000 20_US \ 1- wait 20 ms
11055 %011 TOP_LCD \ 2- send DB5=DB4=1
11056 #205 20_US \ 3- wait 4,1 ms
11057 %011 TOP_LCD \ 4- send again DB5=DB4=1
11058 #5 20_US \ 5- wait 0,1 ms
11059 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11060 #2 20_US \ wait 40 us = LCD cycle
11061 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11062 #2 20_US \ wait 40 us = LCD cycle
11063 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11064 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11065 LCD_CLEAR \ 10- "LCD_Clear"
11066 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11067 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11068 LCD_CLEAR \ 10- "LCD_Clear"
11069 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11070 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11071 CR ." I love you" \ display message on LCD
11072 ['] CR >BODY IS CR \ CR executes its default value
11073 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11074 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11075 ABORT \ ...and end APP_INIT with ABORT, no return.
11078 \ ------------------------------\
11079 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
11080 \ ------------------------------\
11081 MOV #SLEEP,X \ replace default background process
11082 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
11083 MOV #WARM,X \ replace default WARM
11084 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
11085 MOV X,PC \ then execute it
11088 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11092 CODE 20_US \ n -- n * 20 us
11093 BEGIN \ here we presume that LCD_TIM_IFG = 1...
11095 BIT #1,&LCD_TIM_CTL \ 3
11096 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
11097 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
11099 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
11104 CODE TOP_LCD \ LCD Sample
11105 \ \ if write : %xxxxWWWW --
11106 \ \ if read : -- %0000RRRR
11107 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11108 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11109 0= IF \ write LCD bits pattern
11110 AND.B #LCD_DB,TOS \
11111 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11112 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11115 THEN \ read LCD bits pattern
11118 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11119 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11120 AND.B #LCD_DB,TOS \
11124 CODE LCD_WRC \ char -- Write Char
11125 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11127 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11128 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11129 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11130 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11131 COLON \ high level word starts here
11132 TOP_LCD 2 20_US \ write high nibble first
11136 CODE LCD_WRF \ func -- Write Fonction
11137 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11141 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
11142 : LCD_HOME $02 LCD_WRF 100 20_us ;
11144 \ [UNDEFINED] OR [IF]
11146 \ \ https://forth-standard.org/standard/core/OR
11147 \ \ C OR x1 x2 -- x3 logical OR
11155 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
11156 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
11157 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
11158 \ : LCD_FN_SET $20 OR LCD_WrF ;
11159 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
11160 \ : LCD_GOTO $80 OR LCD_WrF ;
11163 \ CODE LCD_RDS \ -- status Read Status
11164 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11165 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11166 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11167 \ COLON \ starts a FORTH word
11168 \ TOP_LCD 2 20_us \ -- %0000HHHH
11169 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11170 \ HI2LO \ switch from FORTH to assembler
11171 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11172 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11173 \ MOV @RSP+,IP \ restore IP saved by COLON
11177 \ CODE LCD_RDC \ -- char Read Char
11178 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11183 \ ******************************\
11184 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11185 \ ******************************\
11186 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
11187 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
11188 BIT.B #SW2,&SW2_IN \ test switch S2
11189 0= IF \ case of switch S2 pressed
11190 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
11192 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
11195 BIT.B #SW1,&SW1_IN \ test switch S1 input
11196 0= IF \ case of Switch S1 pressed
11197 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
11199 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
11203 BW1 \ from quit on truncated RC5 message, repeated RC5 command
11207 \ ******************************\
11208 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11209 \ ******************************\
11210 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11211 \ ******************************\
11212 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11213 \ \ SMclock = 8|16|24 MHz
11214 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
11215 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
11216 \ \ SR(9)=new Toggle bit memory (ADD on)
11217 \ ******************************\
11218 \ RC5_FirstStartBitHalfCycle: \
11219 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
11220 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
11221 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
11222 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
11224 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
11225 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
11227 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
11228 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
11230 MOV #1778,X \ RC5_Period * 1us
11231 MOV #14,W \ count of loop
11233 \ ******************************\
11234 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
11235 \ ******************************\ |
11236 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
11237 \ RC5_Compute_3/4_Period: \ |
11238 RRUM #1,X \ X=1/2 cycle |
11241 ADD X,Y \ Y=3/4 cycle
11242 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
11244 \ ******************************\
11245 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
11246 \ ******************************\
11247 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11248 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
11249 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11250 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11251 SUB #1,W \ decrement count loop
11252 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
11253 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11254 0<> WHILE \ ----> out of loop ----+
11255 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
11257 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
11258 CMP Y,X \ 1 | cycle time out of bound ?
11259 U>= IF \ 2 ^ | yes:
11260 BIC #$30,&RC5_TIM_CTL \ | | stop timer
11261 GOTO BW1 \ | | quit on truncated RC5 message
11263 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
11265 REPEAT \ ----> loop back --+ | with X = new RC5_period value
11266 \ ******************************\ |
11267 \ RC5_SampleEndOf: \ <---------------------+
11268 \ ******************************\
11269 BIC #$30,&RC5_TIM_CTL \ stop timer
11270 \ ******************************\
11271 \ RC5_ComputeNewRC5word \
11272 \ ******************************\
11273 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
11274 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
11275 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
11276 \ ******************************\
11277 \ RC5_ComputeC6bit \
11278 \ ******************************\
11279 BIT #BIT14,T \ test /C6 bit in T
11280 0= IF BIS #BIT6,X \ set C6 bit in X
11281 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
11282 \ ******************************\
11283 \ RC5_CommandByteIsDone \ -- BASE RC5_code
11284 \ ******************************\
11285 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11286 \ ******************************\
11287 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
11288 XOR @RSP,T \ (new XOR old) Toggle bits
11289 BIT #UF10,T \ repeated RC5_command ?
11290 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
11291 XOR #UF10,0(RSP) \ 5 toggle bit memory
11292 \ ******************************\
11293 \ Display IR_RC5 code \
11294 \ ******************************\
11295 SUB #8,PSP \ TOS -- x x x x TOS
11296 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
11297 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
11298 MOV #$10,&BASEADR \ set hexadecimal base
11299 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
11300 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
11301 LO2HI \ switch from assembler to FORTH
11302 LCD_CLEAR \ set LCD cursor at home
11303 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
11304 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
11305 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
11306 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
11307 HI2LO \ -- switch from FORTH to assembler
11308 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
11309 MOV @PSP+,TOS \ -- TOS
11313 \ ------------------------------\
11315 \ ------------------------------\
11317 \ ... \ insert here your background task
11320 CALL &RXON \ comment this line to disable TERMINAL
11322 \ ******************************\
11323 \ here start all interrupts \
11324 \ ******************************\
11325 \ here return all interrupts \
11326 \ ******************************\
11330 \ ------------------------------\
11331 CODE STOP \ stops multitasking, must to be used before downloading app
11332 \ ------------------------------\
11333 \ restore default action of primary DEFERred word SLEEP (assembly version)
11334 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
11335 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
11336 MOV X,-2(X) \ restore the default background
11337 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
11338 ['] WARM >BODY IS WARM \ restore the default WARM
11340 ." RC5toLCD is removed. type START to restart"
11341 COLD \ performs reset to reset all interrupt vectors.
11344 \ ------------------------------\
11345 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
11346 \ ------------------------------\
11347 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
11348 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11349 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11350 \ -- \ID input divider \ 10 = /4
11351 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11352 \ - \TBCLR TimerB Clear
11355 \ -------------------------------\
11356 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11357 \ -- \CM Capture Mode
11362 \ --- \OUTMOD \ 011 = set/reset
11368 \ -------------------------------\
11370 \ -------------------------------\
11372 \ ------------------------------\
11373 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11374 \ ------------------------------\
11375 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11376 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11377 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
11378 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11380 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
11381 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11383 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
11384 \ ------------------------------\
11385 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11386 \ ------------------------------\
11387 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
11388 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11389 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11390 \ ------------------------------\
11391 BIS.B #LCDVo,&LCDVo_DIR \
11392 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
11393 \ ------------------------------\
11394 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11395 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11396 \ ------------------------------\
11397 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11398 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11399 \ ******************************\
11401 \ ******************************\
11402 BIS.B #RC5,&IR_IE \ enable RC5_Int
11403 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11404 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11405 \ ******************************\
11406 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11407 \ ******************************\
11408 \ %01 0001 0100 \ TAxCTL
11409 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
11410 \ -- \ ID divided by 1
11411 \ -- \ MC MODE = up to TAxCCRn
11412 \ - \ TACLR clear timer count
11415 \ ------------------------------\
11416 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
11417 \ ------------------------------\
11419 \ --- \ TAIDEX pre divisor
11420 \ ------------------------------\
11421 \ %0000 0000 0000 0101 \ TAxCCR0
11422 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11423 \ ------------------------------\
11424 \ %0000 0000 0001 0000 \ TAxCCTL0
11425 \ - \ CAP capture/compare mode = compare
11428 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
11429 \ ------------------------------\
11430 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11431 \ ------------------------------\
11432 \ define LPM mode for ACCEPT \
11433 \ ------------------------------\
11434 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11435 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11436 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11437 \ ------------------------------\
11439 \ ------------------------------\
11440 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
11441 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11442 \ ------------------------------\
11443 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11444 \ ------------------------------\
11445 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
11446 \ CMP #2,Y \ Power_ON event
11447 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11449 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
11451 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11453 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11455 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11456 \ ------------------------------\
11458 \ ------------------------------\
11460 \ ------------------------------\
11461 #1000 20_US \ 1- wait 20 ms
11462 %011 TOP_LCD \ 2- send DB5=DB4=1
11463 #205 20_US \ 3- wait 4,1 ms
11464 %011 TOP_LCD \ 4- send again DB5=DB4=1
11465 #5 20_US \ 5- wait 0,1 ms
11466 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11467 #2 20_US \ wait 40 us = LCD cycle
11468 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11469 #2 20_US \ wait 40 us = LCD cycle
11470 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11471 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11472 LCD_CLEAR \ 10- "LCD_Clear"
11473 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11474 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11475 LCD_CLEAR \ 10- "LCD_Clear"
11476 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11477 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11478 CR ." I love you" \ display message on LCD
11479 ['] CR >BODY IS CR \ CR executes its default value
11480 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11481 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11482 ABORT \ ...and end APP_INIT with ABORT, no return.
11485 \ ------------------------------\
11486 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
11487 \ ------------------------------\
11488 MOV #SLEEP,X \ replace default background process
11489 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
11490 MOV #WARM,X \ replace default WARM
11491 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
11492 MOV X,PC \ then execute it
11495 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11499 CODE 20_US \ n -- n * 20 us
11500 BEGIN \ here we presume that LCD_TIM_IFG = 1...
11502 BIT #1,&LCD_TIM_CTL \ 3
11503 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
11504 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
11506 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
11511 CODE TOP_LCD \ LCD Sample
11512 \ \ if write : %xxxxWWWW --
11513 \ \ if read : -- %0000RRRR
11514 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11515 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11516 0= IF \ write LCD bits pattern
11517 AND.B #LCD_DB,TOS \
11518 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11519 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11522 THEN \ read LCD bits pattern
11525 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11526 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11527 AND.B #LCD_DB,TOS \
11531 CODE LCD_WRC \ char -- Write Char
11532 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11534 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11535 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11536 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11537 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11538 COLON \ high level word starts here
11539 TOP_LCD 2 20_US \ write high nibble first
11543 CODE LCD_WRF \ func -- Write Fonction
11544 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11548 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
11549 : LCD_HOME $02 LCD_WRF 100 20_us ;
11551 \ [UNDEFINED] OR [IF]
11553 \ \ https://forth-standard.org/standard/core/OR
11554 \ \ C OR x1 x2 -- x3 logical OR
11562 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
11563 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
11564 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
11565 \ : LCD_FN_SET $20 OR LCD_WrF ;
11566 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
11567 \ : LCD_GOTO $80 OR LCD_WrF ;
11570 \ CODE LCD_RDS \ -- status Read Status
11571 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11572 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11573 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11574 \ COLON \ starts a FORTH word
11575 \ TOP_LCD 2 20_us \ -- %0000HHHH
11576 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11577 \ HI2LO \ switch from FORTH to assembler
11578 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11579 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11580 \ MOV @RSP+,IP \ restore IP saved by COLON
11584 \ CODE LCD_RDC \ -- char Read Char
11585 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11590 \ ******************************\
11591 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11592 \ ******************************\
11593 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
11594 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
11595 BIT.B #SW2,&SW2_IN \ test switch S2
11596 0= IF \ case of switch S2 pressed
11597 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
11599 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
11602 BIT.B #SW1,&SW1_IN \ test switch S1 input
11603 0= IF \ case of Switch S1 pressed
11604 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
11606 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
11610 BW1 \ from quit on truncated RC5 message, repeated RC5 command
11614 \ ******************************\
11615 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11616 \ ******************************\
11617 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11618 \ ******************************\
11619 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11620 \ \ SMclock = 8|16|24 MHz
11621 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
11622 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
11623 \ \ SR(9)=new Toggle bit memory (ADD on)
11624 \ ******************************\
11625 \ RC5_FirstStartBitHalfCycle: \
11626 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
11627 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
11628 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
11629 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
11631 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
11632 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
11634 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
11635 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
11637 MOV #1778,X \ RC5_Period * 1us
11638 MOV #14,W \ count of loop
11640 \ ******************************\
11641 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
11642 \ ******************************\ |
11643 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
11644 \ RC5_Compute_3/4_Period: \ |
11645 RRUM #1,X \ X=1/2 cycle |
11648 ADD X,Y \ Y=3/4 cycle
11649 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
11651 \ ******************************\
11652 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
11653 \ ******************************\
11654 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11655 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
11656 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11657 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11658 SUB #1,W \ decrement count loop
11659 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
11660 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11661 0<> WHILE \ ----> out of loop ----+
11662 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
11664 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
11665 CMP Y,X \ 1 | cycle time out of bound ?
11666 U>= IF \ 2 ^ | yes:
11667 BIC #$30,&RC5_TIM_CTL \ | | stop timer
11668 GOTO BW1 \ | | quit on truncated RC5 message
11670 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
11672 REPEAT \ ----> loop back --+ | with X = new RC5_period value
11673 \ ******************************\ |
11674 \ RC5_SampleEndOf: \ <---------------------+
11675 \ ******************************\
11676 BIC #$30,&RC5_TIM_CTL \ stop timer
11677 \ ******************************\
11678 \ RC5_ComputeNewRC5word \
11679 \ ******************************\
11680 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
11681 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
11682 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
11683 \ ******************************\
11684 \ RC5_ComputeC6bit \
11685 \ ******************************\
11686 BIT #BIT14,T \ test /C6 bit in T
11687 0= IF BIS #BIT6,X \ set C6 bit in X
11688 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
11689 \ ******************************\
11690 \ RC5_CommandByteIsDone \ -- BASE RC5_code
11691 \ ******************************\
11692 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11693 \ ******************************\
11694 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
11695 XOR @RSP,T \ (new XOR old) Toggle bits
11696 BIT #UF10,T \ repeated RC5_command ?
11697 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
11698 XOR #UF10,0(RSP) \ 5 toggle bit memory
11699 \ ******************************\
11700 \ Display IR_RC5 code \
11701 \ ******************************\
11702 SUB #8,PSP \ TOS -- x x x x TOS
11703 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
11704 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
11705 MOV #$10,&BASEADR \ set hexadecimal base
11706 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
11707 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
11708 LO2HI \ switch from assembler to FORTH
11709 LCD_CLEAR \ set LCD cursor at home
11710 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
11711 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
11712 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
11713 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
11714 HI2LO \ -- switch from FORTH to assembler
11715 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
11716 MOV @PSP+,TOS \ -- TOS
11720 \ ------------------------------\
11722 \ ------------------------------\
11724 \ ... \ insert here your background task
11727 CALL &RXON \ comment this line to disable TERMINAL
11729 \ ******************************\
11730 \ here start all interrupts \
11731 \ ******************************\
11732 \ here return all interrupts \
11733 \ ******************************\
11737 \ ------------------------------\
11738 CODE STOP \ stops multitasking, must to be used before downloading app
11739 \ ------------------------------\
11740 \ restore default action of primary DEFERred word SLEEP (assembly version)
11741 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
11742 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
11743 MOV X,-2(X) \ restore the default background
11744 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
11745 ['] WARM >BODY IS WARM \ restore the default WARM
11747 ." RC5toLCD is removed. type START to restart"
11748 COLD \ performs reset to reset all interrupt vectors.
11751 \ ------------------------------\
11752 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
11753 \ ------------------------------\
11754 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
11755 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11756 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11757 \ -- \ID input divider \ 10 = /4
11758 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11759 \ - \TBCLR TimerB Clear
11762 \ -------------------------------\
11763 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11764 \ -- \CM Capture Mode
11769 \ --- \OUTMOD \ 011 = set/reset
11775 \ -------------------------------\
11777 \ -------------------------------\
11779 \ ------------------------------\
11780 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11781 \ ------------------------------\
11782 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11783 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11784 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
11785 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11787 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
11788 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11790 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
11791 \ ------------------------------\
11792 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11793 \ ------------------------------\
11794 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
11795 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11796 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11797 \ ------------------------------\
11798 BIS.B #LCDVo,&LCDVo_DIR \
11799 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
11800 \ ------------------------------\
11801 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11802 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11803 \ ------------------------------\
11804 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11805 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11806 \ ******************************\
11808 \ ******************************\
11809 BIS.B #RC5,&IR_IE \ enable RC5_Int
11810 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11811 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11812 \ ******************************\
11813 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11814 \ ******************************\
11815 \ %01 0001 0100 \ TAxCTL
11816 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
11817 \ -- \ ID divided by 1
11818 \ -- \ MC MODE = up to TAxCCRn
11819 \ - \ TACLR clear timer count
11822 \ ------------------------------\
11823 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
11824 \ ------------------------------\
11826 \ --- \ TAIDEX pre divisor
11827 \ ------------------------------\
11828 \ %0000 0000 0000 0101 \ TAxCCR0
11829 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11830 \ ------------------------------\
11831 \ %0000 0000 0001 0000 \ TAxCCTL0
11832 \ - \ CAP capture/compare mode = compare
11835 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
11836 \ ------------------------------\
11837 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11838 \ ------------------------------\
11839 \ define LPM mode for ACCEPT \
11840 \ ------------------------------\
11841 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11842 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11843 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11844 \ ------------------------------\
11846 \ ------------------------------\
11847 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
11848 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11849 \ ------------------------------\
11850 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11851 \ ------------------------------\
11852 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
11853 \ CMP #2,Y \ Power_ON event
11854 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11856 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
11858 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11860 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11862 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11863 \ ------------------------------\
11865 \ ------------------------------\
11867 \ ------------------------------\
11868 #1000 20_US \ 1- wait 20 ms
11869 %011 TOP_LCD \ 2- send DB5=DB4=1
11870 #205 20_US \ 3- wait 4,1 ms
11871 %011 TOP_LCD \ 4- send again DB5=DB4=1
11872 #5 20_US \ 5- wait 0,1 ms
11873 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11874 #2 20_US \ wait 40 us = LCD cycle
11875 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11876 #2 20_US \ wait 40 us = LCD cycle
11877 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11878 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11879 LCD_CLEAR \ 10- "LCD_Clear"
11880 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11881 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11882 LCD_CLEAR \ 10- "LCD_Clear"
11883 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11884 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11885 CR ." I love you" \ display message on LCD
11886 ['] CR >BODY IS CR \ CR executes its default value
11887 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11888 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11889 ABORT \ ...and end APP_INIT with ABORT, no return.
11892 \ ------------------------------\
11893 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
11894 \ ------------------------------\
11895 MOV #SLEEP,X \ replace default background process
11896 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
11897 MOV #WARM,X \ replace default WARM
11898 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
11899 MOV X,PC \ then execute it
11902 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11906 CODE 20_US \ n -- n * 20 us
11907 BEGIN \ here we presume that LCD_TIM_IFG = 1...
11909 BIT #1,&LCD_TIM_CTL \ 3
11910 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
11911 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
11913 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
11918 CODE TOP_LCD \ LCD Sample
11919 \ \ if write : %xxxxWWWW --
11920 \ \ if read : -- %0000RRRR
11921 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11922 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11923 0= IF \ write LCD bits pattern
11924 AND.B #LCD_DB,TOS \
11925 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11926 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11929 THEN \ read LCD bits pattern
11932 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11933 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11934 AND.B #LCD_DB,TOS \
11938 CODE LCD_WRC \ char -- Write Char
11939 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11941 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11942 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11943 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11944 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11945 COLON \ high level word starts here
11946 TOP_LCD 2 20_US \ write high nibble first
11950 CODE LCD_WRF \ func -- Write Fonction
11951 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11955 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
11956 : LCD_HOME $02 LCD_WRF 100 20_us ;
11958 \ [UNDEFINED] OR [IF]
11960 \ \ https://forth-standard.org/standard/core/OR
11961 \ \ C OR x1 x2 -- x3 logical OR
11969 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
11970 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
11971 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
11972 \ : LCD_FN_SET $20 OR LCD_WrF ;
11973 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
11974 \ : LCD_GOTO $80 OR LCD_WrF ;
11977 \ CODE LCD_RDS \ -- status Read Status
11978 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11979 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11980 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11981 \ COLON \ starts a FORTH word
11982 \ TOP_LCD 2 20_us \ -- %0000HHHH
11983 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11984 \ HI2LO \ switch from FORTH to assembler
11985 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11986 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11987 \ MOV @RSP+,IP \ restore IP saved by COLON
11991 \ CODE LCD_RDC \ -- char Read Char
11992 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11997 \ ******************************\
11998 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11999 \ ******************************\
12000 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12001 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12002 BIT.B #SW2,&SW2_IN \ test switch S2
12003 0= IF \ case of switch S2 pressed
12004 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12006 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12009 BIT.B #SW1,&SW1_IN \ test switch S1 input
12010 0= IF \ case of Switch S1 pressed
12011 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12013 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12017 BW1 \ from quit on truncated RC5 message, repeated RC5 command
12021 \ ******************************\
12022 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12023 \ ******************************\
12024 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12025 \ ******************************\
12026 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12027 \ \ SMclock = 8|16|24 MHz
12028 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12029 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12030 \ \ SR(9)=new Toggle bit memory (ADD on)
12031 \ ******************************\
12032 \ RC5_FirstStartBitHalfCycle: \
12033 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12034 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12035 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12036 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12038 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12039 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12041 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12042 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12044 MOV #1778,X \ RC5_Period * 1us
12045 MOV #14,W \ count of loop
12047 \ ******************************\
12048 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12049 \ ******************************\ |
12050 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12051 \ RC5_Compute_3/4_Period: \ |
12052 RRUM #1,X \ X=1/2 cycle |
12055 ADD X,Y \ Y=3/4 cycle
12056 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12058 \ ******************************\
12059 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12060 \ ******************************\
12061 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12062 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12063 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12064 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12065 SUB #1,W \ decrement count loop
12066 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12067 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12068 0<> WHILE \ ----> out of loop ----+
12069 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12071 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12072 CMP Y,X \ 1 | cycle time out of bound ?
12073 U>= IF \ 2 ^ | yes:
12074 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12075 GOTO BW1 \ | | quit on truncated RC5 message
12077 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12079 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12080 \ ******************************\ |
12081 \ RC5_SampleEndOf: \ <---------------------+
12082 \ ******************************\
12083 BIC #$30,&RC5_TIM_CTL \ stop timer
12084 \ ******************************\
12085 \ RC5_ComputeNewRC5word \
12086 \ ******************************\
12087 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12088 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12089 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12090 \ ******************************\
12091 \ RC5_ComputeC6bit \
12092 \ ******************************\
12093 BIT #BIT14,T \ test /C6 bit in T
12094 0= IF BIS #BIT6,X \ set C6 bit in X
12095 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12096 \ ******************************\
12097 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12098 \ ******************************\
12099 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12100 \ ******************************\
12101 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
12102 XOR @RSP,T \ (new XOR old) Toggle bits
12103 BIT #UF10,T \ repeated RC5_command ?
12104 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
12105 XOR #UF10,0(RSP) \ 5 toggle bit memory
12106 \ ******************************\
12107 \ Display IR_RC5 code \
12108 \ ******************************\
12109 SUB #8,PSP \ TOS -- x x x x TOS
12110 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
12111 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
12112 MOV #$10,&BASEADR \ set hexadecimal base
12113 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
12114 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
12115 LO2HI \ switch from assembler to FORTH
12116 LCD_CLEAR \ set LCD cursor at home
12117 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
12118 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
12119 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
12120 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
12121 HI2LO \ -- switch from FORTH to assembler
12122 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
12123 MOV @PSP+,TOS \ -- TOS
12127 \ ------------------------------\
12129 \ ------------------------------\
12131 \ ... \ insert here your background task
12134 CALL &RXON \ comment this line to disable TERMINAL
12136 \ ******************************\
12137 \ here start all interrupts \
12138 \ ******************************\
12139 \ here return all interrupts \
12140 \ ******************************\
12144 \ ------------------------------\
12145 CODE STOP \ stops multitasking, must to be used before downloading app
12146 \ ------------------------------\
12147 \ restore default action of primary DEFERred word SLEEP (assembly version)
12148 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
12149 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12150 MOV X,-2(X) \ restore the default background
12151 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
12152 ['] WARM >BODY IS WARM \ restore the default WARM
12154 ." RC5toLCD is removed. type START to restart"
12155 COLD \ performs reset to reset all interrupt vectors.
12158 \ ------------------------------\
12159 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
12160 \ ------------------------------\
12161 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
12162 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12163 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12164 \ -- \ID input divider \ 10 = /4
12165 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12166 \ - \TBCLR TimerB Clear
12169 \ -------------------------------\
12170 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12171 \ -- \CM Capture Mode
12176 \ --- \OUTMOD \ 011 = set/reset
12182 \ -------------------------------\
12184 \ -------------------------------\
12186 \ ------------------------------\
12187 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12188 \ ------------------------------\
12189 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12190 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12191 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
12192 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12194 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
12195 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12197 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
12198 \ ------------------------------\
12199 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12200 \ ------------------------------\
12201 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
12202 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12203 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12204 \ ------------------------------\
12205 BIS.B #LCDVo,&LCDVo_DIR \
12206 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
12207 \ ------------------------------\
12208 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12209 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12210 \ ------------------------------\
12211 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12212 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12213 \ ******************************\
12215 \ ******************************\
12216 BIS.B #RC5,&IR_IE \ enable RC5_Int
12217 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12218 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12219 \ ******************************\
12220 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12221 \ ******************************\
12222 \ %01 0001 0100 \ TAxCTL
12223 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
12224 \ -- \ ID divided by 1
12225 \ -- \ MC MODE = up to TAxCCRn
12226 \ - \ TACLR clear timer count
12229 \ ------------------------------\
12230 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
12231 \ ------------------------------\
12233 \ --- \ TAIDEX pre divisor
12234 \ ------------------------------\
12235 \ %0000 0000 0000 0101 \ TAxCCR0
12236 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12237 \ ------------------------------\
12238 \ %0000 0000 0001 0000 \ TAxCCTL0
12239 \ - \ CAP capture/compare mode = compare
12242 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
12243 \ ------------------------------\
12244 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12245 \ ------------------------------\
12246 \ define LPM mode for ACCEPT \
12247 \ ------------------------------\
12248 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12249 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12250 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12251 \ ------------------------------\
12253 \ ------------------------------\
12254 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
12255 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
12256 \ ------------------------------\
12257 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
12258 \ ------------------------------\
12259 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
12260 \ CMP #2,Y \ Power_ON event
12261 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
12263 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
12265 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
12267 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
12269 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
12270 \ ------------------------------\
12272 \ ------------------------------\
12274 \ ------------------------------\
12275 #1000 20_US \ 1- wait 20 ms
12276 %011 TOP_LCD \ 2- send DB5=DB4=1
12277 #205 20_US \ 3- wait 4,1 ms
12278 %011 TOP_LCD \ 4- send again DB5=DB4=1
12279 #5 20_US \ 5- wait 0,1 ms
12280 %011 TOP_LCD \ 6- send again again DB5=DB4=1
12281 #2 20_US \ wait 40 us = LCD cycle
12282 %010 TOP_LCD \ 7- send DB5=1 DB4=0
12283 #2 20_US \ wait 40 us = LCD cycle
12284 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12285 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12286 LCD_CLEAR \ 10- "LCD_Clear"
12287 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12288 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12289 LCD_CLEAR \ 10- "LCD_Clear"
12290 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12291 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12292 CR ." I love you" \ display message on LCD
12293 ['] CR >BODY IS CR \ CR executes its default value
12294 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
12295 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
12296 ABORT \ ...and end APP_INIT with ABORT, no return.
12299 \ ------------------------------\
12300 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
12301 \ ------------------------------\
12302 MOV #SLEEP,X \ replace default background process
12303 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
12304 MOV #WARM,X \ replace default WARM
12305 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
12306 MOV X,PC \ then execute it
12309 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
12313 CODE 20_US \ n -- n * 20 us
12314 BEGIN \ here we presume that LCD_TIM_IFG = 1...
12316 BIT #1,&LCD_TIM_CTL \ 3
12317 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
12318 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
12320 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
12325 CODE TOP_LCD \ LCD Sample
12326 \ \ if write : %xxxxWWWW --
12327 \ \ if read : -- %0000RRRR
12328 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12329 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12330 0= IF \ write LCD bits pattern
12331 AND.B #LCD_DB,TOS \
12332 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12333 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12336 THEN \ read LCD bits pattern
12339 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12340 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12341 AND.B #LCD_DB,TOS \
12345 CODE LCD_WRC \ char -- Write Char
12346 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12348 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
12349 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
12350 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12351 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12352 COLON \ high level word starts here
12353 TOP_LCD 2 20_US \ write high nibble first
12357 CODE LCD_WRF \ func -- Write Fonction
12358 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12362 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
12363 : LCD_HOME $02 LCD_WRF 100 20_us ;
12365 \ [UNDEFINED] OR [IF]
12367 \ \ https://forth-standard.org/standard/core/OR
12368 \ \ C OR x1 x2 -- x3 logical OR
12376 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
12377 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
12378 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
12379 \ : LCD_FN_SET $20 OR LCD_WrF ;
12380 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
12381 \ : LCD_GOTO $80 OR LCD_WrF ;
12384 \ CODE LCD_RDS \ -- status Read Status
12385 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12386 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12387 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12388 \ COLON \ starts a FORTH word
12389 \ TOP_LCD 2 20_us \ -- %0000HHHH
12390 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
12391 \ HI2LO \ switch from FORTH to assembler
12392 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
12393 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
12394 \ MOV @RSP+,IP \ restore IP saved by COLON
12398 \ CODE LCD_RDC \ -- char Read Char
12399 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12404 \ ******************************\
12405 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12406 \ ******************************\
12407 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12408 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12409 BIT.B #SW2,&SW2_IN \ test switch S2
12410 0= IF \ case of switch S2 pressed
12411 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12413 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12416 BIT.B #SW1,&SW1_IN \ test switch S1 input
12417 0= IF \ case of Switch S1 pressed
12418 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12420 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12424 BW1 \ from quit on truncated RC5 message, repeated RC5 command
12428 \ ******************************\
12429 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12430 \ ******************************\
12431 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12432 \ ******************************\
12433 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12434 \ \ SMclock = 8|16|24 MHz
12435 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12436 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12437 \ \ SR(9)=new Toggle bit memory (ADD on)
12438 \ ******************************\
12439 \ RC5_FirstStartBitHalfCycle: \
12440 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12441 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12442 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12443 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12445 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12446 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12448 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12449 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12451 MOV #1778,X \ RC5_Period * 1us
12452 MOV #14,W \ count of loop
12454 \ ******************************\
12455 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12456 \ ******************************\ |
12457 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12458 \ RC5_Compute_3/4_Period: \ |
12459 RRUM #1,X \ X=1/2 cycle |
12462 ADD X,Y \ Y=3/4 cycle
12463 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12465 \ ******************************\
12466 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12467 \ ******************************\
12468 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12469 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12470 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12471 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12472 SUB #1,W \ decrement count loop
12473 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12474 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12475 0<> WHILE \ ----> out of loop ----+
12476 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12478 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12479 CMP Y,X \ 1 | cycle time out of bound ?
12480 U>= IF \ 2 ^ | yes:
12481 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12482 GOTO BW1 \ | | quit on truncated RC5 message
12484 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12486 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12487 \ ******************************\ |
12488 \ RC5_SampleEndOf: \ <---------------------+
12489 \ ******************************\
12490 BIC #$30,&RC5_TIM_CTL \ stop timer
12491 \ ******************************\
12492 \ RC5_ComputeNewRC5word \
12493 \ ******************************\
12494 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12495 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12496 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12497 \ ******************************\
12498 \ RC5_ComputeC6bit \
12499 \ ******************************\
12500 BIT #BIT14,T \ test /C6 bit in T
12501 0= IF BIS #BIT6,X \ set C6 bit in X
12502 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12503 \ ******************************\
12504 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12505 \ ******************************\
12506 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12507 \ ******************************\
12508 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
12509 XOR @RSP,T \ (new XOR old) Toggle bits
12510 BIT #UF10,T \ repeated RC5_command ?
12511 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
12512 XOR #UF10,0(RSP) \ 5 toggle bit memory
12513 \ ******************************\
12514 \ Display IR_RC5 code \
12515 \ ******************************\
12516 SUB #8,PSP \ TOS -- x x x x TOS
12517 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
12518 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
12519 MOV #$10,&BASEADR \ set hexadecimal base
12520 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
12521 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
12522 LO2HI \ switch from assembler to FORTH
12523 LCD_CLEAR \ set LCD cursor at home
12524 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
12525 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
12526 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
12527 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
12528 HI2LO \ -- switch from FORTH to assembler
12529 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
12530 MOV @PSP+,TOS \ -- TOS
12534 \ ------------------------------\
12536 \ ------------------------------\
12538 \ ... \ insert here your background task
12541 CALL &RXON \ comment this line to disable TERMINAL
12543 \ ******************************\
12544 \ here start all interrupts \
12545 \ ******************************\
12546 \ here return all interrupts \
12547 \ ******************************\
12551 \ ------------------------------\
12552 CODE STOP \ stops multitasking, must to be used before downloading app
12553 \ ------------------------------\
12554 \ restore default action of primary DEFERred word SLEEP (assembly version)
12555 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
12556 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12557 MOV X,-2(X) \ restore the default background
12558 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
12559 ['] WARM >BODY IS WARM \ restore the default WARM
12561 ." RC5toLCD is removed. type START to restart"
12562 COLD \ performs reset to reset all interrupt vectors.
12565 \ ------------------------------\
12566 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
12567 \ ------------------------------\
12568 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
12569 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12570 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12571 \ -- \ID input divider \ 10 = /4
12572 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12573 \ - \TBCLR TimerB Clear
12576 \ -------------------------------\
12577 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12578 \ -- \CM Capture Mode
12583 \ --- \OUTMOD \ 011 = set/reset
12589 \ -------------------------------\
12591 \ -------------------------------\
12593 \ ------------------------------\
12594 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12595 \ ------------------------------\
12596 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12597 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12598 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
12599 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12601 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
12602 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12604 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
12605 \ ------------------------------\
12606 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12607 \ ------------------------------\
12608 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
12609 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12610 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12611 \ ------------------------------\
12612 BIS.B #LCDVo,&LCDVo_DIR \
12613 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
12614 \ ------------------------------\
12615 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12616 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12617 \ ------------------------------\
12618 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12619 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12620 \ ******************************\
12622 \ ******************************\
12623 BIS.B #RC5,&IR_IE \ enable RC5_Int
12624 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12625 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12626 \ ******************************\
12627 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12628 \ ******************************\
12629 \ %01 0001 0100 \ TAxCTL
12630 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
12631 \ -- \ ID divided by 1
12632 \ -- \ MC MODE = up to TAxCCRn
12633 \ - \ TACLR clear timer count
12636 \ ------------------------------\
12637 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
12638 \ ------------------------------\
12640 \ --- \ TAIDEX pre divisor
12641 \ ------------------------------\
12642 \ %0000 0000 0000 0101 \ TAxCCR0
12643 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12644 \ ------------------------------\
12645 \ %0000 0000 0001 0000 \ TAxCCTL0
12646 \ - \ CAP capture/compare mode = compare
12649 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
12650 \ ------------------------------\
12651 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12652 \ ------------------------------\
12653 \ define LPM mode for ACCEPT \
12654 \ ------------------------------\
12655 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12656 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12657 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12658 \ ------------------------------\
12660 \ ------------------------------\
12661 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
12662 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
12663 \ ------------------------------\
12664 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
12665 \ ------------------------------\
12666 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
12667 \ CMP #2,Y \ Power_ON event
12668 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
12670 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
12672 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
12674 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
12676 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
12677 \ ------------------------------\
12679 \ ------------------------------\
12681 \ ------------------------------\
12682 #1000 20_US \ 1- wait 20 ms
12683 %011 TOP_LCD \ 2- send DB5=DB4=1
12684 #205 20_US \ 3- wait 4,1 ms
12685 %011 TOP_LCD \ 4- send again DB5=DB4=1
12686 #5 20_US \ 5- wait 0,1 ms
12687 %011 TOP_LCD \ 6- send again again DB5=DB4=1
12688 #2 20_US \ wait 40 us = LCD cycle
12689 %010 TOP_LCD \ 7- send DB5=1 DB4=0
12690 #2 20_US \ wait 40 us = LCD cycle
12691 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12692 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12693 LCD_CLEAR \ 10- "LCD_Clear"
12694 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12695 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12696 LCD_CLEAR \ 10- "LCD_Clear"
12697 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12698 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12699 CR ." I love you" \ display message on LCD
12700 ['] CR >BODY IS CR \ CR executes its default value
12701 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
12702 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
12703 ABORT \ ...and end APP_INIT with ABORT, no return.
12706 \ ------------------------------\
12707 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
12708 \ ------------------------------\
12709 MOV #SLEEP,X \ replace default background process
12710 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
12711 MOV #WARM,X \ replace default WARM
12712 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
12713 MOV X,PC \ then execute it
12716 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
12720 CODE 20_US \ n -- n * 20 us
12721 BEGIN \ here we presume that LCD_TIM_IFG = 1...
12723 BIT #1,&LCD_TIM_CTL \ 3
12724 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
12725 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
12727 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
12732 CODE TOP_LCD \ LCD Sample
12733 \ \ if write : %xxxxWWWW --
12734 \ \ if read : -- %0000RRRR
12735 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12736 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12737 0= IF \ write LCD bits pattern
12738 AND.B #LCD_DB,TOS \
12739 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12740 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12743 THEN \ read LCD bits pattern
12746 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12747 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12748 AND.B #LCD_DB,TOS \
12752 CODE LCD_WRC \ char -- Write Char
12753 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12755 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
12756 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
12757 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12758 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12759 COLON \ high level word starts here
12760 TOP_LCD 2 20_US \ write high nibble first
12764 CODE LCD_WRF \ func -- Write Fonction
12765 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12769 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
12770 : LCD_HOME $02 LCD_WRF 100 20_us ;
12772 \ [UNDEFINED] OR [IF]
12774 \ \ https://forth-standard.org/standard/core/OR
12775 \ \ C OR x1 x2 -- x3 logical OR
12783 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
12784 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
12785 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
12786 \ : LCD_FN_SET $20 OR LCD_WrF ;
12787 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
12788 \ : LCD_GOTO $80 OR LCD_WrF ;
12791 \ CODE LCD_RDS \ -- status Read Status
12792 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12793 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12794 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12795 \ COLON \ starts a FORTH word
12796 \ TOP_LCD 2 20_us \ -- %0000HHHH
12797 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
12798 \ HI2LO \ switch from FORTH to assembler
12799 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
12800 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
12801 \ MOV @RSP+,IP \ restore IP saved by COLON
12805 \ CODE LCD_RDC \ -- char Read Char
12806 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12811 \ ******************************\
12812 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12813 \ ******************************\
12814 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12815 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12816 BIT.B #SW2,&SW2_IN \ test switch S2
12817 0= IF \ case of switch S2 pressed
12818 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12820 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12823 BIT.B #SW1,&SW1_IN \ test switch S1 input
12824 0= IF \ case of Switch S1 pressed
12825 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12827 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12831 BW1 \ from quit on truncated RC5 message, repeated RC5 command
12835 \ ******************************\
12836 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12837 \ ******************************\
12838 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12839 \ ******************************\
12840 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12841 \ \ SMclock = 8|16|24 MHz
12842 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12843 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12844 \ \ SR(9)=new Toggle bit memory (ADD on)
12845 \ ******************************\
12846 \ RC5_FirstStartBitHalfCycle: \
12847 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12848 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12849 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12850 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12852 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12853 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12855 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12856 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12858 MOV #1778,X \ RC5_Period * 1us
12859 MOV #14,W \ count of loop
12861 \ ******************************\
12862 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12863 \ ******************************\ |
12864 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12865 \ RC5_Compute_3/4_Period: \ |
12866 RRUM #1,X \ X=1/2 cycle |
12869 ADD X,Y \ Y=3/4 cycle
12870 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12872 \ ******************************\
12873 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12874 \ ******************************\
12875 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12876 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12877 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12878 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12879 SUB #1,W \ decrement count loop
12880 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12881 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12882 0<> WHILE \ ----> out of loop ----+
12883 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12885 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12886 CMP Y,X \ 1 | cycle time out of bound ?
12887 U>= IF \ 2 ^ | yes:
12888 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12889 GOTO BW1 \ | | quit on truncated RC5 message
12891 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12893 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12894 \ ******************************\ |
12895 \ RC5_SampleEndOf: \ <---------------------+
12896 \ ******************************\
12897 BIC #$30,&RC5_TIM_CTL \ stop timer
12898 \ ******************************\
12899 \ RC5_ComputeNewRC5word \
12900 \ ******************************\
12901 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12902 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12903 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12904 \ ******************************\
12905 \ RC5_ComputeC6bit \
12906 \ ******************************\
12907 BIT #BIT14,T \ test /C6 bit in T
12908 0= IF BIS #BIT6,X \ set C6 bit in X
12909 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12910 \ ******************************\
12911 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12912 \ ******************************\
12913 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12914 \ ******************************\
12915 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
12916 XOR @RSP,T \ (new XOR old) Toggle bits
12917 BIT #UF10,T \ repeated RC5_command ?
12918 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
12919 XOR #UF10,0(RSP) \ 5 toggle bit memory
12920 \ ******************************\
12921 \ Display IR_RC5 code \
12922 \ ******************************\
12923 SUB #8,PSP \ TOS -- x x x x TOS
12924 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
12925 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
12926 MOV #$10,&BASEADR \ set hexadecimal base
12927 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
12928 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
12929 LO2HI \ switch from assembler to FORTH
12930 LCD_CLEAR \ set LCD cursor at home
12931 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
12932 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
12933 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
12934 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
12935 HI2LO \ -- switch from FORTH to assembler
12936 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
12937 MOV @PSP+,TOS \ -- TOS
12941 \ ------------------------------\
12943 \ ------------------------------\
12945 \ ... \ insert here your background task
12948 CALL &RXON \ comment this line to disable TERMINAL
12950 \ ******************************\
12951 \ here start all interrupts \
12952 \ ******************************\
12953 \ here return all interrupts \
12954 \ ******************************\
12958 \ ------------------------------\
12959 CODE STOP \ stops multitasking, must to be used before downloading app
12960 \ ------------------------------\
12961 \ restore default action of primary DEFERred word SLEEP (assembly version)
12962 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
12963 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12964 MOV X,-2(X) \ restore the default background
12965 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
12966 ['] WARM >BODY IS WARM \ restore the default WARM
12968 ." RC5toLCD is removed. type START to restart"
12969 COLD \ performs reset to reset all interrupt vectors.
12972 \ ------------------------------\
12973 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
12974 \ ------------------------------\
12975 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
12976 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12977 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12978 \ -- \ID input divider \ 10 = /4
12979 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12980 \ - \TBCLR TimerB Clear
12983 \ -------------------------------\
12984 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12985 \ -- \CM Capture Mode
12990 \ --- \OUTMOD \ 011 = set/reset
12996 \ -------------------------------\
12998 \ -------------------------------\
13000 \ ------------------------------\
13001 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13002 \ ------------------------------\
13003 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13004 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13005 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
13006 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13008 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
13009 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13011 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
13012 \ ------------------------------\
13013 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13014 \ ------------------------------\
13015 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
13016 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13017 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13018 \ ------------------------------\
13019 BIS.B #LCDVo,&LCDVo_DIR \
13020 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
13021 \ ------------------------------\
13022 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13023 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13024 \ ------------------------------\
13025 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13026 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13027 \ ******************************\
13029 \ ******************************\
13030 BIS.B #RC5,&IR_IE \ enable RC5_Int
13031 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13032 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13033 \ ******************************\
13034 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13035 \ ******************************\
13036 \ %01 0001 0100 \ TAxCTL
13037 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
13038 \ -- \ ID divided by 1
13039 \ -- \ MC MODE = up to TAxCCRn
13040 \ - \ TACLR clear timer count
13043 \ ------------------------------\
13044 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
13045 \ ------------------------------\
13047 \ --- \ TAIDEX pre divisor
13048 \ ------------------------------\
13049 \ %0000 0000 0000 0101 \ TAxCCR0
13050 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13051 \ ------------------------------\
13052 \ %0000 0000 0001 0000 \ TAxCCTL0
13053 \ - \ CAP capture/compare mode = compare
13056 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
13057 \ ------------------------------\
13058 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13059 \ ------------------------------\
13060 \ define LPM mode for ACCEPT \
13061 \ ------------------------------\
13062 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13063 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13064 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13065 \ ------------------------------\
13067 \ ------------------------------\
13068 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
13069 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
13070 \ ------------------------------\
13071 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
13072 \ ------------------------------\
13073 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
13074 \ CMP #2,Y \ Power_ON event
13075 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13077 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
13079 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13081 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13083 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13084 \ ------------------------------\
13086 \ ------------------------------\
13088 \ ------------------------------\
13089 #1000 20_US \ 1- wait 20 ms
13090 %011 TOP_LCD \ 2- send DB5=DB4=1
13091 #205 20_US \ 3- wait 4,1 ms
13092 %011 TOP_LCD \ 4- send again DB5=DB4=1
13093 #5 20_US \ 5- wait 0,1 ms
13094 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13095 #2 20_US \ wait 40 us = LCD cycle
13096 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13097 #2 20_US \ wait 40 us = LCD cycle
13098 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13099 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13100 LCD_CLEAR \ 10- "LCD_Clear"
13101 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13102 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13103 LCD_CLEAR \ 10- "LCD_Clear"
13104 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13105 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13106 CR ." I love you" \ display message on LCD
13107 ['] CR >BODY IS CR \ CR executes its default value
13108 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13109 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13110 ABORT \ ...and end APP_INIT with ABORT, no return.
13113 \ ------------------------------\
13114 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
13115 \ ------------------------------\
13116 MOV #SLEEP,X \ replace default background process
13117 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
13118 MOV #WARM,X \ replace default WARM
13119 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
13120 MOV X,PC \ then execute it
13123 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13127 CODE 20_US \ n -- n * 20 us
13128 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13130 BIT #1,&LCD_TIM_CTL \ 3
13131 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13132 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13134 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13139 CODE TOP_LCD \ LCD Sample
13140 \ \ if write : %xxxxWWWW --
13141 \ \ if read : -- %0000RRRR
13142 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13143 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13144 0= IF \ write LCD bits pattern
13145 AND.B #LCD_DB,TOS \
13146 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13147 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13150 THEN \ read LCD bits pattern
13153 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13154 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13155 AND.B #LCD_DB,TOS \
13159 CODE LCD_WRC \ char -- Write Char
13160 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13162 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13163 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13164 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13165 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13166 COLON \ high level word starts here
13167 TOP_LCD 2 20_US \ write high nibble first
13171 CODE LCD_WRF \ func -- Write Fonction
13172 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13176 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13177 : LCD_HOME $02 LCD_WRF 100 20_us ;
13179 \ [UNDEFINED] OR [IF]
13181 \ \ https://forth-standard.org/standard/core/OR
13182 \ \ C OR x1 x2 -- x3 logical OR
13190 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
13191 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
13192 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
13193 \ : LCD_FN_SET $20 OR LCD_WrF ;
13194 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
13195 \ : LCD_GOTO $80 OR LCD_WrF ;
13198 \ CODE LCD_RDS \ -- status Read Status
13199 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13200 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13201 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13202 \ COLON \ starts a FORTH word
13203 \ TOP_LCD 2 20_us \ -- %0000HHHH
13204 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13205 \ HI2LO \ switch from FORTH to assembler
13206 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13207 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13208 \ MOV @RSP+,IP \ restore IP saved by COLON
13212 \ CODE LCD_RDC \ -- char Read Char
13213 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13218 \ ******************************\
13219 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13220 \ ******************************\
13221 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13222 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
13223 BIT.B #SW2,&SW2_IN \ test switch S2
13224 0= IF \ case of switch S2 pressed
13225 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13227 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
13230 BIT.B #SW1,&SW1_IN \ test switch S1 input
13231 0= IF \ case of Switch S1 pressed
13232 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13234 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13238 BW1 \ from quit on truncated RC5 message, repeated RC5 command
13242 \ ******************************\
13243 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13244 \ ******************************\
13245 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13246 \ ******************************\
13247 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13248 \ \ SMclock = 8|16|24 MHz
13249 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13250 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13251 \ \ SR(9)=new Toggle bit memory (ADD on)
13252 \ ******************************\
13253 \ RC5_FirstStartBitHalfCycle: \
13254 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13255 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13256 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
13257 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
13259 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
13260 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
13262 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
13263 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
13265 MOV #1778,X \ RC5_Period * 1us
13266 MOV #14,W \ count of loop
13268 \ ******************************\
13269 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
13270 \ ******************************\ |
13271 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
13272 \ RC5_Compute_3/4_Period: \ |
13273 RRUM #1,X \ X=1/2 cycle |
13276 ADD X,Y \ Y=3/4 cycle
13277 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
13279 \ ******************************\
13280 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
13281 \ ******************************\
13282 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13283 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
13284 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13285 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13286 SUB #1,W \ decrement count loop
13287 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
13288 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13289 0<> WHILE \ ----> out of loop ----+
13290 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
13292 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
13293 CMP Y,X \ 1 | cycle time out of bound ?
13294 U>= IF \ 2 ^ | yes:
13295 BIC #$30,&RC5_TIM_CTL \ | | stop timer
13296 GOTO BW1 \ | | quit on truncated RC5 message
13298 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
13300 REPEAT \ ----> loop back --+ | with X = new RC5_period value
13301 \ ******************************\ |
13302 \ RC5_SampleEndOf: \ <---------------------+
13303 \ ******************************\
13304 BIC #$30,&RC5_TIM_CTL \ stop timer
13305 \ ******************************\
13306 \ RC5_ComputeNewRC5word \
13307 \ ******************************\
13308 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
13309 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
13310 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
13311 \ ******************************\
13312 \ RC5_ComputeC6bit \
13313 \ ******************************\
13314 BIT #BIT14,T \ test /C6 bit in T
13315 0= IF BIS #BIT6,X \ set C6 bit in X
13316 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
13317 \ ******************************\
13318 \ RC5_CommandByteIsDone \ -- BASE RC5_code
13319 \ ******************************\
13320 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13321 \ ******************************\
13322 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
13323 XOR @RSP,T \ (new XOR old) Toggle bits
13324 BIT #UF10,T \ repeated RC5_command ?
13325 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
13326 XOR #UF10,0(RSP) \ 5 toggle bit memory
13327 \ ******************************\
13328 \ Display IR_RC5 code \
13329 \ ******************************\
13330 SUB #8,PSP \ TOS -- x x x x TOS
13331 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
13332 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
13333 MOV #$10,&BASEADR \ set hexadecimal base
13334 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
13335 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
13336 LO2HI \ switch from assembler to FORTH
13337 LCD_CLEAR \ set LCD cursor at home
13338 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
13339 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
13340 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
13341 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
13342 HI2LO \ -- switch from FORTH to assembler
13343 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
13344 MOV @PSP+,TOS \ -- TOS
13348 \ ------------------------------\
13350 \ ------------------------------\
13352 \ ... \ insert here your background task
13355 CALL &RXON \ comment this line to disable TERMINAL
13357 \ ******************************\
13358 \ here start all interrupts \
13359 \ ******************************\
13360 \ here return all interrupts \
13361 \ ******************************\
13365 \ ------------------------------\
13366 CODE STOP \ stops multitasking, must to be used before downloading app
13367 \ ------------------------------\
13368 \ restore default action of primary DEFERred word SLEEP (assembly version)
13369 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
13370 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
13371 MOV X,-2(X) \ restore the default background
13372 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
13373 ['] WARM >BODY IS WARM \ restore the default WARM
13375 ." RC5toLCD is removed. type START to restart"
13376 COLD \ performs reset to reset all interrupt vectors.
13379 \ ------------------------------\
13380 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
13381 \ ------------------------------\
13382 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
13383 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13384 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13385 \ -- \ID input divider \ 10 = /4
13386 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
13387 \ - \TBCLR TimerB Clear
13390 \ -------------------------------\
13391 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13392 \ -- \CM Capture Mode
13397 \ --- \OUTMOD \ 011 = set/reset
13403 \ -------------------------------\
13405 \ -------------------------------\
13407 \ ------------------------------\
13408 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13409 \ ------------------------------\
13410 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13411 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13412 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
13413 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13415 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
13416 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13418 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
13419 \ ------------------------------\
13420 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13421 \ ------------------------------\
13422 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
13423 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13424 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13425 \ ------------------------------\
13426 BIS.B #LCDVo,&LCDVo_DIR \
13427 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
13428 \ ------------------------------\
13429 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13430 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13431 \ ------------------------------\
13432 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13433 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13434 \ ******************************\
13436 \ ******************************\
13437 BIS.B #RC5,&IR_IE \ enable RC5_Int
13438 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13439 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13440 \ ******************************\
13441 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13442 \ ******************************\
13443 \ %01 0001 0100 \ TAxCTL
13444 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
13445 \ -- \ ID divided by 1
13446 \ -- \ MC MODE = up to TAxCCRn
13447 \ - \ TACLR clear timer count
13450 \ ------------------------------\
13451 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
13452 \ ------------------------------\
13454 \ --- \ TAIDEX pre divisor
13455 \ ------------------------------\
13456 \ %0000 0000 0000 0101 \ TAxCCR0
13457 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13458 \ ------------------------------\
13459 \ %0000 0000 0001 0000 \ TAxCCTL0
13460 \ - \ CAP capture/compare mode = compare
13463 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
13464 \ ------------------------------\
13465 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13466 \ ------------------------------\
13467 \ define LPM mode for ACCEPT \
13468 \ ------------------------------\
13469 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13470 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13471 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13472 \ ------------------------------\
13474 \ ------------------------------\
13475 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
13476 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
13477 \ ------------------------------\
13478 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
13479 \ ------------------------------\
13480 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
13481 \ CMP #2,Y \ Power_ON event
13482 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13484 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
13486 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13488 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13490 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13491 \ ------------------------------\
13493 \ ------------------------------\
13495 \ ------------------------------\
13496 #1000 20_US \ 1- wait 20 ms
13497 %011 TOP_LCD \ 2- send DB5=DB4=1
13498 #205 20_US \ 3- wait 4,1 ms
13499 %011 TOP_LCD \ 4- send again DB5=DB4=1
13500 #5 20_US \ 5- wait 0,1 ms
13501 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13502 #2 20_US \ wait 40 us = LCD cycle
13503 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13504 #2 20_US \ wait 40 us = LCD cycle
13505 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13506 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13507 LCD_CLEAR \ 10- "LCD_Clear"
13508 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13509 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13510 LCD_CLEAR \ 10- "LCD_Clear"
13511 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13512 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13513 CR ." I love you" \ display message on LCD
13514 ['] CR >BODY IS CR \ CR executes its default value
13515 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13516 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13517 ABORT \ ...and end APP_INIT with ABORT, no return.
13520 \ ------------------------------\
13521 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
13522 \ ------------------------------\
13523 MOV #SLEEP,X \ replace default background process
13524 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
13525 MOV #WARM,X \ replace default WARM
13526 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
13527 MOV X,PC \ then execute it
13530 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13534 CODE 20_US \ n -- n * 20 us
13535 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13537 BIT #1,&LCD_TIM_CTL \ 3
13538 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13539 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13541 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13546 CODE TOP_LCD \ LCD Sample
13547 \ \ if write : %xxxxWWWW --
13548 \ \ if read : -- %0000RRRR
13549 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13550 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13551 0= IF \ write LCD bits pattern
13552 AND.B #LCD_DB,TOS \
13553 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13554 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13557 THEN \ read LCD bits pattern
13560 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13561 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13562 AND.B #LCD_DB,TOS \
13566 CODE LCD_WRC \ char -- Write Char
13567 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13569 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13570 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13571 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13572 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13573 COLON \ high level word starts here
13574 TOP_LCD 2 20_US \ write high nibble first
13578 CODE LCD_WRF \ func -- Write Fonction
13579 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13583 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13584 : LCD_HOME $02 LCD_WRF 100 20_us ;
13586 \ [UNDEFINED] OR [IF]
13588 \ \ https://forth-standard.org/standard/core/OR
13589 \ \ C OR x1 x2 -- x3 logical OR
13597 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
13598 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
13599 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
13600 \ : LCD_FN_SET $20 OR LCD_WrF ;
13601 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
13602 \ : LCD_GOTO $80 OR LCD_WrF ;
13605 \ CODE LCD_RDS \ -- status Read Status
13606 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13607 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13608 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13609 \ COLON \ starts a FORTH word
13610 \ TOP_LCD 2 20_us \ -- %0000HHHH
13611 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13612 \ HI2LO \ switch from FORTH to assembler
13613 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13614 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13615 \ MOV @RSP+,IP \ restore IP saved by COLON
13619 \ CODE LCD_RDC \ -- char Read Char
13620 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13625 \ ******************************\
13626 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13627 \ ******************************\
13628 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13629 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
13630 BIT.B #SW2,&SW2_IN \ test switch S2
13631 0= IF \ case of switch S2 pressed
13632 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13634 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
13637 BIT.B #SW1,&SW1_IN \ test switch S1 input
13638 0= IF \ case of Switch S1 pressed
13639 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13641 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13645 BW1 \ from quit on truncated RC5 message, repeated RC5 command
13649 \ ******************************\
13650 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13651 \ ******************************\
13652 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13653 \ ******************************\
13654 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13655 \ \ SMclock = 8|16|24 MHz
13656 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13657 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13658 \ \ SR(9)=new Toggle bit memory (ADD on)
13659 \ ******************************\
13660 \ RC5_FirstStartBitHalfCycle: \
13661 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13662 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13663 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
13664 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
13666 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
13667 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
13669 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
13670 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
13672 MOV #1778,X \ RC5_Period * 1us
13673 MOV #14,W \ count of loop
13675 \ ******************************\
13676 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
13677 \ ******************************\ |
13678 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
13679 \ RC5_Compute_3/4_Period: \ |
13680 RRUM #1,X \ X=1/2 cycle |
13683 ADD X,Y \ Y=3/4 cycle
13684 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
13686 \ ******************************\
13687 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
13688 \ ******************************\
13689 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13690 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
13691 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13692 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13693 SUB #1,W \ decrement count loop
13694 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
13695 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13696 0<> WHILE \ ----> out of loop ----+
13697 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
13699 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
13700 CMP Y,X \ 1 | cycle time out of bound ?
13701 U>= IF \ 2 ^ | yes:
13702 BIC #$30,&RC5_TIM_CTL \ | | stop timer
13703 GOTO BW1 \ | | quit on truncated RC5 message
13705 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
13707 REPEAT \ ----> loop back --+ | with X = new RC5_period value
13708 \ ******************************\ |
13709 \ RC5_SampleEndOf: \ <---------------------+
13710 \ ******************************\
13711 BIC #$30,&RC5_TIM_CTL \ stop timer
13712 \ ******************************\
13713 \ RC5_ComputeNewRC5word \
13714 \ ******************************\
13715 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
13716 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
13717 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
13718 \ ******************************\
13719 \ RC5_ComputeC6bit \
13720 \ ******************************\
13721 BIT #BIT14,T \ test /C6 bit in T
13722 0= IF BIS #BIT6,X \ set C6 bit in X
13723 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
13724 \ ******************************\
13725 \ RC5_CommandByteIsDone \ -- BASE RC5_code
13726 \ ******************************\
13727 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13728 \ ******************************\
13729 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
13730 XOR @RSP,T \ (new XOR old) Toggle bits
13731 BIT #UF10,T \ repeated RC5_command ?
13732 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
13733 XOR #UF10,0(RSP) \ 5 toggle bit memory
13734 \ ******************************\
13735 \ Display IR_RC5 code \
13736 \ ******************************\
13737 SUB #8,PSP \ TOS -- x x x x TOS
13738 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
13739 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
13740 MOV #$10,&BASEADR \ set hexadecimal base
13741 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
13742 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
13743 LO2HI \ switch from assembler to FORTH
13744 LCD_CLEAR \ set LCD cursor at home
13745 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
13746 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
13747 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
13748 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
13749 HI2LO \ -- switch from FORTH to assembler
13750 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
13751 MOV @PSP+,TOS \ -- TOS
13755 \ ------------------------------\
13757 \ ------------------------------\
13759 \ ... \ insert here your background task
13762 CALL &RXON \ comment this line to disable TERMINAL
13764 \ ******************************\
13765 \ here start all interrupts \
13766 \ ******************************\
13767 \ here return all interrupts \
13768 \ ******************************\
13772 \ ------------------------------\
13773 CODE STOP \ stops multitasking, must to be used before downloading app
13774 \ ------------------------------\
13775 \ restore default action of primary DEFERred word SLEEP (assembly version)
13776 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
13777 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
13778 MOV X,-2(X) \ restore the default background
13779 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
13780 ['] WARM >BODY IS WARM \ restore the default WARM
13782 ." RC5toLCD is removed. type START to restart"
13783 COLD \ performs reset to reset all interrupt vectors.
13786 \ ------------------------------\
13787 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
13788 \ ------------------------------\
13789 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
13790 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13791 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13792 \ -- \ID input divider \ 10 = /4
13793 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
13794 \ - \TBCLR TimerB Clear
13797 \ -------------------------------\
13798 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13799 \ -- \CM Capture Mode
13804 \ --- \OUTMOD \ 011 = set/reset
13810 \ -------------------------------\
13812 \ -------------------------------\
13814 \ ------------------------------\
13815 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13816 \ ------------------------------\
13817 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13818 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13819 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
13820 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13822 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
13823 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13825 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
13826 \ ------------------------------\
13827 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13828 \ ------------------------------\
13829 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
13830 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13831 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13832 \ ------------------------------\
13833 BIS.B #LCDVo,&LCDVo_DIR \
13834 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
13835 \ ------------------------------\
13836 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13837 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13838 \ ------------------------------\
13839 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13840 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13841 \ ******************************\
13843 \ ******************************\
13844 BIS.B #RC5,&IR_IE \ enable RC5_Int
13845 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13846 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13847 \ ******************************\
13848 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13849 \ ******************************\
13850 \ %01 0001 0100 \ TAxCTL
13851 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
13852 \ -- \ ID divided by 1
13853 \ -- \ MC MODE = up to TAxCCRn
13854 \ - \ TACLR clear timer count
13857 \ ------------------------------\
13858 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
13859 \ ------------------------------\
13861 \ --- \ TAIDEX pre divisor
13862 \ ------------------------------\
13863 \ %0000 0000 0000 0101 \ TAxCCR0
13864 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13865 \ ------------------------------\
13866 \ %0000 0000 0001 0000 \ TAxCCTL0
13867 \ - \ CAP capture/compare mode = compare
13870 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
13871 \ ------------------------------\
13872 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13873 \ ------------------------------\
13874 \ define LPM mode for ACCEPT \
13875 \ ------------------------------\
13876 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13877 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13878 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13879 \ ------------------------------\
13881 \ ------------------------------\
13882 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
13883 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
13884 \ ------------------------------\
13885 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
13886 \ ------------------------------\
13887 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
13888 \ CMP #2,Y \ Power_ON event
13889 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13891 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
13893 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13895 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13897 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13898 \ ------------------------------\
13900 \ ------------------------------\
13902 \ ------------------------------\
13903 #1000 20_US \ 1- wait 20 ms
13904 %011 TOP_LCD \ 2- send DB5=DB4=1
13905 #205 20_US \ 3- wait 4,1 ms
13906 %011 TOP_LCD \ 4- send again DB5=DB4=1
13907 #5 20_US \ 5- wait 0,1 ms
13908 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13909 #2 20_US \ wait 40 us = LCD cycle
13910 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13911 #2 20_US \ wait 40 us = LCD cycle
13912 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13913 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13914 LCD_CLEAR \ 10- "LCD_Clear"
13915 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13916 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13917 LCD_CLEAR \ 10- "LCD_Clear"
13918 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13919 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13920 CR ." I love you" \ display message on LCD
13921 ['] CR >BODY IS CR \ CR executes its default value
13922 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13923 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13924 ABORT \ ...and end APP_INIT with ABORT, no return.
13927 \ ------------------------------\
13928 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
13929 \ ------------------------------\
13930 MOV #SLEEP,X \ replace default background process
13931 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
13932 MOV #WARM,X \ replace default WARM
13933 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
13934 MOV X,PC \ then execute it
13937 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13941 CODE 20_US \ n -- n * 20 us
13942 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13944 BIT #1,&LCD_TIM_CTL \ 3
13945 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13946 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13948 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13953 CODE TOP_LCD \ LCD Sample
13954 \ \ if write : %xxxxWWWW --
13955 \ \ if read : -- %0000RRRR
13956 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13957 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13958 0= IF \ write LCD bits pattern
13959 AND.B #LCD_DB,TOS \
13960 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13961 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13964 THEN \ read LCD bits pattern
13967 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13968 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13969 AND.B #LCD_DB,TOS \
13973 CODE LCD_WRC \ char -- Write Char
13974 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13976 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13977 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13978 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13979 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13980 COLON \ high level word starts here
13981 TOP_LCD 2 20_US \ write high nibble first
13985 CODE LCD_WRF \ func -- Write Fonction
13986 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13990 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13991 : LCD_HOME $02 LCD_WRF 100 20_us ;
13993 \ [UNDEFINED] OR [IF]
13995 \ \ https://forth-standard.org/standard/core/OR
13996 \ \ C OR x1 x2 -- x3 logical OR
14004 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
14005 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
14006 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
14007 \ : LCD_FN_SET $20 OR LCD_WrF ;
14008 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
14009 \ : LCD_GOTO $80 OR LCD_WrF ;
14012 \ CODE LCD_RDS \ -- status Read Status
14013 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14014 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14015 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14016 \ COLON \ starts a FORTH word
14017 \ TOP_LCD 2 20_us \ -- %0000HHHH
14018 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14019 \ HI2LO \ switch from FORTH to assembler
14020 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14021 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14022 \ MOV @RSP+,IP \ restore IP saved by COLON
14026 \ CODE LCD_RDC \ -- char Read Char
14027 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14032 \ ******************************\
14033 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14034 \ ******************************\
14035 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14036 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
14037 BIT.B #SW2,&SW2_IN \ test switch S2
14038 0= IF \ case of switch S2 pressed
14039 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14041 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
14044 BIT.B #SW1,&SW1_IN \ test switch S1 input
14045 0= IF \ case of Switch S1 pressed
14046 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14048 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14052 BW1 \ from quit on truncated RC5 message, repeated RC5 command
14056 \ ******************************\
14057 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14058 \ ******************************\
14059 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14060 \ ******************************\
14061 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14062 \ \ SMclock = 8|16|24 MHz
14063 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14064 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14065 \ \ SR(9)=new Toggle bit memory (ADD on)
14066 \ ******************************\
14067 \ RC5_FirstStartBitHalfCycle: \
14068 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14069 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14070 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
14071 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
14073 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
14074 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
14076 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
14077 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
14079 MOV #1778,X \ RC5_Period * 1us
14080 MOV #14,W \ count of loop
14082 \ ******************************\
14083 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14084 \ ******************************\ |
14085 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14086 \ RC5_Compute_3/4_Period: \ |
14087 RRUM #1,X \ X=1/2 cycle |
14090 ADD X,Y \ Y=3/4 cycle
14091 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14093 \ ******************************\
14094 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14095 \ ******************************\
14096 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14097 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14098 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14099 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14100 SUB #1,W \ decrement count loop
14101 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14102 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14103 0<> WHILE \ ----> out of loop ----+
14104 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14106 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14107 CMP Y,X \ 1 | cycle time out of bound ?
14108 U>= IF \ 2 ^ | yes:
14109 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14110 GOTO BW1 \ | | quit on truncated RC5 message
14112 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14114 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14115 \ ******************************\ |
14116 \ RC5_SampleEndOf: \ <---------------------+
14117 \ ******************************\
14118 BIC #$30,&RC5_TIM_CTL \ stop timer
14119 \ ******************************\
14120 \ RC5_ComputeNewRC5word \
14121 \ ******************************\
14122 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14123 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14124 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14125 \ ******************************\
14126 \ RC5_ComputeC6bit \
14127 \ ******************************\
14128 BIT #BIT14,T \ test /C6 bit in T
14129 0= IF BIS #BIT6,X \ set C6 bit in X
14130 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14131 \ ******************************\
14132 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14133 \ ******************************\
14134 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14135 \ ******************************\
14136 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14137 XOR @RSP,T \ (new XOR old) Toggle bits
14138 BIT #UF10,T \ repeated RC5_command ?
14139 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
14140 XOR #UF10,0(RSP) \ 5 toggle bit memory
14141 \ ******************************\
14142 \ Display IR_RC5 code \
14143 \ ******************************\
14144 SUB #8,PSP \ TOS -- x x x x TOS
14145 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14146 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14147 MOV #$10,&BASEADR \ set hexadecimal base
14148 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14149 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14150 LO2HI \ switch from assembler to FORTH
14151 LCD_CLEAR \ set LCD cursor at home
14152 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14153 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14154 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14155 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14156 HI2LO \ -- switch from FORTH to assembler
14157 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14158 MOV @PSP+,TOS \ -- TOS
14162 \ ------------------------------\
14164 \ ------------------------------\
14166 \ ... \ insert here your background task
14169 CALL &RXON \ comment this line to disable TERMINAL
14171 \ ******************************\
14172 \ here start all interrupts \
14173 \ ******************************\
14174 \ here return all interrupts \
14175 \ ******************************\
14179 \ ------------------------------\
14180 CODE STOP \ stops multitasking, must to be used before downloading app
14181 \ ------------------------------\
14182 \ restore default action of primary DEFERred word SLEEP (assembly version)
14183 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
14184 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14185 MOV X,-2(X) \ restore the default background
14186 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
14187 ['] WARM >BODY IS WARM \ restore the default WARM
14189 ." RC5toLCD is removed. type START to restart"
14190 COLD \ performs reset to reset all interrupt vectors.
14193 \ ------------------------------\
14194 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
14195 \ ------------------------------\
14196 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
14197 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14198 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14199 \ -- \ID input divider \ 10 = /4
14200 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14201 \ - \TBCLR TimerB Clear
14204 \ -------------------------------\
14205 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14206 \ -- \CM Capture Mode
14211 \ --- \OUTMOD \ 011 = set/reset
14217 \ -------------------------------\
14219 \ -------------------------------\
14221 \ ------------------------------\
14222 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14223 \ ------------------------------\
14224 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14225 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14226 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
14227 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14229 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
14230 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14232 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
14233 \ ------------------------------\
14234 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14235 \ ------------------------------\
14236 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
14237 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14238 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14239 \ ------------------------------\
14240 BIS.B #LCDVo,&LCDVo_DIR \
14241 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
14242 \ ------------------------------\
14243 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14244 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14245 \ ------------------------------\
14246 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14247 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14248 \ ******************************\
14250 \ ******************************\
14251 BIS.B #RC5,&IR_IE \ enable RC5_Int
14252 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14253 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14254 \ ******************************\
14255 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14256 \ ******************************\
14257 \ %01 0001 0100 \ TAxCTL
14258 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
14259 \ -- \ ID divided by 1
14260 \ -- \ MC MODE = up to TAxCCRn
14261 \ - \ TACLR clear timer count
14264 \ ------------------------------\
14265 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
14266 \ ------------------------------\
14268 \ --- \ TAIDEX pre divisor
14269 \ ------------------------------\
14270 \ %0000 0000 0000 0101 \ TAxCCR0
14271 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14272 \ ------------------------------\
14273 \ %0000 0000 0001 0000 \ TAxCCTL0
14274 \ - \ CAP capture/compare mode = compare
14277 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
14278 \ ------------------------------\
14279 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14280 \ ------------------------------\
14281 \ define LPM mode for ACCEPT \
14282 \ ------------------------------\
14283 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14284 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14285 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14286 \ ------------------------------\
14288 \ ------------------------------\
14289 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
14290 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
14291 \ ------------------------------\
14292 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
14293 \ ------------------------------\
14294 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
14295 \ CMP #2,Y \ Power_ON event
14296 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
14298 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
14300 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
14302 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
14304 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
14305 \ ------------------------------\
14307 \ ------------------------------\
14309 \ ------------------------------\
14310 #1000 20_US \ 1- wait 20 ms
14311 %011 TOP_LCD \ 2- send DB5=DB4=1
14312 #205 20_US \ 3- wait 4,1 ms
14313 %011 TOP_LCD \ 4- send again DB5=DB4=1
14314 #5 20_US \ 5- wait 0,1 ms
14315 %011 TOP_LCD \ 6- send again again DB5=DB4=1
14316 #2 20_US \ wait 40 us = LCD cycle
14317 %010 TOP_LCD \ 7- send DB5=1 DB4=0
14318 #2 20_US \ wait 40 us = LCD cycle
14319 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14320 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14321 LCD_CLEAR \ 10- "LCD_Clear"
14322 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14323 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14324 LCD_CLEAR \ 10- "LCD_Clear"
14325 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14326 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14327 CR ." I love you" \ display message on LCD
14328 ['] CR >BODY IS CR \ CR executes its default value
14329 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
14330 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14331 ABORT \ ...and end APP_INIT with ABORT, no return.
14334 \ ------------------------------\
14335 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
14336 \ ------------------------------\
14337 MOV #SLEEP,X \ replace default background process
14338 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
14339 MOV #WARM,X \ replace default WARM
14340 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
14341 MOV X,PC \ then execute it
14344 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
14348 CODE 20_US \ n -- n * 20 us
14349 BEGIN \ here we presume that LCD_TIM_IFG = 1...
14351 BIT #1,&LCD_TIM_CTL \ 3
14352 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
14353 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
14355 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
14360 CODE TOP_LCD \ LCD Sample
14361 \ \ if write : %xxxxWWWW --
14362 \ \ if read : -- %0000RRRR
14363 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14364 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14365 0= IF \ write LCD bits pattern
14366 AND.B #LCD_DB,TOS \
14367 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14368 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14371 THEN \ read LCD bits pattern
14374 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14375 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14376 AND.B #LCD_DB,TOS \
14380 CODE LCD_WRC \ char -- Write Char
14381 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14383 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
14384 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
14385 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14386 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14387 COLON \ high level word starts here
14388 TOP_LCD 2 20_US \ write high nibble first
14392 CODE LCD_WRF \ func -- Write Fonction
14393 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14397 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
14398 : LCD_HOME $02 LCD_WRF 100 20_us ;
14400 \ [UNDEFINED] OR [IF]
14402 \ \ https://forth-standard.org/standard/core/OR
14403 \ \ C OR x1 x2 -- x3 logical OR
14411 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
14412 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
14413 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
14414 \ : LCD_FN_SET $20 OR LCD_WrF ;
14415 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
14416 \ : LCD_GOTO $80 OR LCD_WrF ;
14419 \ CODE LCD_RDS \ -- status Read Status
14420 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14421 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14422 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14423 \ COLON \ starts a FORTH word
14424 \ TOP_LCD 2 20_us \ -- %0000HHHH
14425 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14426 \ HI2LO \ switch from FORTH to assembler
14427 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14428 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14429 \ MOV @RSP+,IP \ restore IP saved by COLON
14433 \ CODE LCD_RDC \ -- char Read Char
14434 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14439 \ ******************************\
14440 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14441 \ ******************************\
14442 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14443 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
14444 BIT.B #SW2,&SW2_IN \ test switch S2
14445 0= IF \ case of switch S2 pressed
14446 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14448 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
14451 BIT.B #SW1,&SW1_IN \ test switch S1 input
14452 0= IF \ case of Switch S1 pressed
14453 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14455 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14459 BW1 \ from quit on truncated RC5 message, repeated RC5 command
14463 \ ******************************\
14464 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14465 \ ******************************\
14466 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14467 \ ******************************\
14468 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14469 \ \ SMclock = 8|16|24 MHz
14470 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14471 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14472 \ \ SR(9)=new Toggle bit memory (ADD on)
14473 \ ******************************\
14474 \ RC5_FirstStartBitHalfCycle: \
14475 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14476 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14477 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
14478 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
14480 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
14481 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
14483 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
14484 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
14486 MOV #1778,X \ RC5_Period * 1us
14487 MOV #14,W \ count of loop
14489 \ ******************************\
14490 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14491 \ ******************************\ |
14492 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14493 \ RC5_Compute_3/4_Period: \ |
14494 RRUM #1,X \ X=1/2 cycle |
14497 ADD X,Y \ Y=3/4 cycle
14498 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14500 \ ******************************\
14501 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14502 \ ******************************\
14503 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14504 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14505 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14506 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14507 SUB #1,W \ decrement count loop
14508 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14509 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14510 0<> WHILE \ ----> out of loop ----+
14511 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14513 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14514 CMP Y,X \ 1 | cycle time out of bound ?
14515 U>= IF \ 2 ^ | yes:
14516 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14517 GOTO BW1 \ | | quit on truncated RC5 message
14519 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14521 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14522 \ ******************************\ |
14523 \ RC5_SampleEndOf: \ <---------------------+
14524 \ ******************************\
14525 BIC #$30,&RC5_TIM_CTL \ stop timer
14526 \ ******************************\
14527 \ RC5_ComputeNewRC5word \
14528 \ ******************************\
14529 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14530 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14531 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14532 \ ******************************\
14533 \ RC5_ComputeC6bit \
14534 \ ******************************\
14535 BIT #BIT14,T \ test /C6 bit in T
14536 0= IF BIS #BIT6,X \ set C6 bit in X
14537 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14538 \ ******************************\
14539 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14540 \ ******************************\
14541 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14542 \ ******************************\
14543 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14544 XOR @RSP,T \ (new XOR old) Toggle bits
14545 BIT #UF10,T \ repeated RC5_command ?
14546 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
14547 XOR #UF10,0(RSP) \ 5 toggle bit memory
14548 \ ******************************\
14549 \ Display IR_RC5 code \
14550 \ ******************************\
14551 SUB #8,PSP \ TOS -- x x x x TOS
14552 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14553 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14554 MOV #$10,&BASEADR \ set hexadecimal base
14555 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14556 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14557 LO2HI \ switch from assembler to FORTH
14558 LCD_CLEAR \ set LCD cursor at home
14559 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14560 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14561 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14562 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14563 HI2LO \ -- switch from FORTH to assembler
14564 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14565 MOV @PSP+,TOS \ -- TOS
14569 \ ------------------------------\
14571 \ ------------------------------\
14573 \ ... \ insert here your background task
14576 CALL &RXON \ comment this line to disable TERMINAL
14578 \ ******************************\
14579 \ here start all interrupts \
14580 \ ******************************\
14581 \ here return all interrupts \
14582 \ ******************************\
14586 \ ------------------------------\
14587 CODE STOP \ stops multitasking, must to be used before downloading app
14588 \ ------------------------------\
14589 \ restore default action of primary DEFERred word SLEEP (assembly version)
14590 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
14591 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14592 MOV X,-2(X) \ restore the default background
14593 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
14594 ['] WARM >BODY IS WARM \ restore the default WARM
14596 ." RC5toLCD is removed. type START to restart"
14597 COLD \ performs reset to reset all interrupt vectors.
14600 \ ------------------------------\
14601 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
14602 \ ------------------------------\
14603 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
14604 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14605 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14606 \ -- \ID input divider \ 10 = /4
14607 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14608 \ - \TBCLR TimerB Clear
14611 \ -------------------------------\
14612 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14613 \ -- \CM Capture Mode
14618 \ --- \OUTMOD \ 011 = set/reset
14624 \ -------------------------------\
14626 \ -------------------------------\
14628 \ ------------------------------\
14629 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14630 \ ------------------------------\
14631 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14632 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14633 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
14634 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14636 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
14637 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14639 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
14640 \ ------------------------------\
14641 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14642 \ ------------------------------\
14643 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
14644 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14645 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14646 \ ------------------------------\
14647 BIS.B #LCDVo,&LCDVo_DIR \
14648 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
14649 \ ------------------------------\
14650 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14651 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14652 \ ------------------------------\
14653 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14654 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14655 \ ******************************\
14657 \ ******************************\
14658 BIS.B #RC5,&IR_IE \ enable RC5_Int
14659 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14660 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14661 \ ******************************\
14662 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14663 \ ******************************\
14664 \ %01 0001 0100 \ TAxCTL
14665 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
14666 \ -- \ ID divided by 1
14667 \ -- \ MC MODE = up to TAxCCRn
14668 \ - \ TACLR clear timer count
14671 \ ------------------------------\
14672 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
14673 \ ------------------------------\
14675 \ --- \ TAIDEX pre divisor
14676 \ ------------------------------\
14677 \ %0000 0000 0000 0101 \ TAxCCR0
14678 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14679 \ ------------------------------\
14680 \ %0000 0000 0001 0000 \ TAxCCTL0
14681 \ - \ CAP capture/compare mode = compare
14684 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
14685 \ ------------------------------\
14686 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14687 \ ------------------------------\
14688 \ define LPM mode for ACCEPT \
14689 \ ------------------------------\
14690 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14691 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14692 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14693 \ ------------------------------\
14695 \ ------------------------------\
14696 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
14697 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
14698 \ ------------------------------\
14699 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
14700 \ ------------------------------\
14701 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
14702 \ CMP #2,Y \ Power_ON event
14703 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
14705 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
14707 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
14709 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
14711 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
14712 \ ------------------------------\
14714 \ ------------------------------\
14716 \ ------------------------------\
14717 #1000 20_US \ 1- wait 20 ms
14718 %011 TOP_LCD \ 2- send DB5=DB4=1
14719 #205 20_US \ 3- wait 4,1 ms
14720 %011 TOP_LCD \ 4- send again DB5=DB4=1
14721 #5 20_US \ 5- wait 0,1 ms
14722 %011 TOP_LCD \ 6- send again again DB5=DB4=1
14723 #2 20_US \ wait 40 us = LCD cycle
14724 %010 TOP_LCD \ 7- send DB5=1 DB4=0
14725 #2 20_US \ wait 40 us = LCD cycle
14726 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14727 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14728 LCD_CLEAR \ 10- "LCD_Clear"
14729 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14730 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14731 LCD_CLEAR \ 10- "LCD_Clear"
14732 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14733 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14734 CR ." I love you" \ display message on LCD
14735 ['] CR >BODY IS CR \ CR executes its default value
14736 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
14737 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14738 ABORT \ ...and end APP_INIT with ABORT, no return.
14741 \ ------------------------------\
14742 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
14743 \ ------------------------------\
14744 MOV #SLEEP,X \ replace default background process
14745 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
14746 MOV #WARM,X \ replace default WARM
14747 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
14748 MOV X,PC \ then execute it
14751 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
14755 CODE 20_US \ n -- n * 20 us
14756 BEGIN \ here we presume that LCD_TIM_IFG = 1...
14758 BIT #1,&LCD_TIM_CTL \ 3
14759 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
14760 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
14762 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
14767 CODE TOP_LCD \ LCD Sample
14768 \ \ if write : %xxxxWWWW --
14769 \ \ if read : -- %0000RRRR
14770 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14771 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14772 0= IF \ write LCD bits pattern
14773 AND.B #LCD_DB,TOS \
14774 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14775 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14778 THEN \ read LCD bits pattern
14781 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14782 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14783 AND.B #LCD_DB,TOS \
14787 CODE LCD_WRC \ char -- Write Char
14788 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14790 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
14791 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
14792 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14793 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14794 COLON \ high level word starts here
14795 TOP_LCD 2 20_US \ write high nibble first
14799 CODE LCD_WRF \ func -- Write Fonction
14800 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14804 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
14805 : LCD_HOME $02 LCD_WRF 100 20_us ;
14807 \ [UNDEFINED] OR [IF]
14809 \ \ https://forth-standard.org/standard/core/OR
14810 \ \ C OR x1 x2 -- x3 logical OR
14818 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
14819 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
14820 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
14821 \ : LCD_FN_SET $20 OR LCD_WrF ;
14822 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
14823 \ : LCD_GOTO $80 OR LCD_WrF ;
14826 \ CODE LCD_RDS \ -- status Read Status
14827 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14828 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14829 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14830 \ COLON \ starts a FORTH word
14831 \ TOP_LCD 2 20_us \ -- %0000HHHH
14832 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14833 \ HI2LO \ switch from FORTH to assembler
14834 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14835 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14836 \ MOV @RSP+,IP \ restore IP saved by COLON
14840 \ CODE LCD_RDC \ -- char Read Char
14841 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14846 \ ******************************\
14847 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14848 \ ******************************\
14849 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14850 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
14851 BIT.B #SW2,&SW2_IN \ test switch S2
14852 0= IF \ case of switch S2 pressed
14853 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14855 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
14858 BIT.B #SW1,&SW1_IN \ test switch S1 input
14859 0= IF \ case of Switch S1 pressed
14860 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14862 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14866 BW1 \ from quit on truncated RC5 message, repeated RC5 command
14870 \ ******************************\
14871 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14872 \ ******************************\
14873 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14874 \ ******************************\
14875 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14876 \ \ SMclock = 8|16|24 MHz
14877 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14878 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14879 \ \ SR(9)=new Toggle bit memory (ADD on)
14880 \ ******************************\
14881 \ RC5_FirstStartBitHalfCycle: \
14882 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14883 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14884 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
14885 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
14887 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
14888 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
14890 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
14891 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
14893 MOV #1778,X \ RC5_Period * 1us
14894 MOV #14,W \ count of loop
14896 \ ******************************\
14897 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14898 \ ******************************\ |
14899 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14900 \ RC5_Compute_3/4_Period: \ |
14901 RRUM #1,X \ X=1/2 cycle |
14904 ADD X,Y \ Y=3/4 cycle
14905 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14907 \ ******************************\
14908 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14909 \ ******************************\
14910 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14911 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14912 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14913 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14914 SUB #1,W \ decrement count loop
14915 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14916 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14917 0<> WHILE \ ----> out of loop ----+
14918 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14920 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14921 CMP Y,X \ 1 | cycle time out of bound ?
14922 U>= IF \ 2 ^ | yes:
14923 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14924 GOTO BW1 \ | | quit on truncated RC5 message
14926 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14928 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14929 \ ******************************\ |
14930 \ RC5_SampleEndOf: \ <---------------------+
14931 \ ******************************\
14932 BIC #$30,&RC5_TIM_CTL \ stop timer
14933 \ ******************************\
14934 \ RC5_ComputeNewRC5word \
14935 \ ******************************\
14936 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14937 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14938 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14939 \ ******************************\
14940 \ RC5_ComputeC6bit \
14941 \ ******************************\
14942 BIT #BIT14,T \ test /C6 bit in T
14943 0= IF BIS #BIT6,X \ set C6 bit in X
14944 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14945 \ ******************************\
14946 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14947 \ ******************************\
14948 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14949 \ ******************************\
14950 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14951 XOR @RSP,T \ (new XOR old) Toggle bits
14952 BIT #UF10,T \ repeated RC5_command ?
14953 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
14954 XOR #UF10,0(RSP) \ 5 toggle bit memory
14955 \ ******************************\
14956 \ Display IR_RC5 code \
14957 \ ******************************\
14958 SUB #8,PSP \ TOS -- x x x x TOS
14959 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14960 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14961 MOV #$10,&BASEADR \ set hexadecimal base
14962 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14963 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14964 LO2HI \ switch from assembler to FORTH
14965 LCD_CLEAR \ set LCD cursor at home
14966 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14967 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14968 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14969 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14970 HI2LO \ -- switch from FORTH to assembler
14971 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14972 MOV @PSP+,TOS \ -- TOS
14976 \ ------------------------------\
14978 \ ------------------------------\
14980 \ ... \ insert here your background task
14983 CALL &RXON \ comment this line to disable TERMINAL
14985 \ ******************************\
14986 \ here start all interrupts \
14987 \ ******************************\
14988 \ here return all interrupts \
14989 \ ******************************\
14993 \ ------------------------------\
14994 CODE STOP \ stops multitasking, must to be used before downloading app
14995 \ ------------------------------\
14996 \ restore default action of primary DEFERred word SLEEP (assembly version)
14997 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
14998 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14999 MOV X,-2(X) \ restore the default background
15000 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15001 ['] WARM >BODY IS WARM \ restore the default WARM
15003 ." RC5toLCD is removed. type START to restart"
15004 COLD \ performs reset to reset all interrupt vectors.
15007 \ ------------------------------\
15008 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
15009 \ ------------------------------\
15010 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15011 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15012 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15013 \ -- \ID input divider \ 10 = /4
15014 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15015 \ - \TBCLR TimerB Clear
15018 \ -------------------------------\
15019 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15020 \ -- \CM Capture Mode
15025 \ --- \OUTMOD \ 011 = set/reset
15031 \ -------------------------------\
15033 \ -------------------------------\
15035 \ ------------------------------\
15036 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15037 \ ------------------------------\
15038 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15039 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15040 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
15041 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15043 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
15044 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15046 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
15047 \ ------------------------------\
15048 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15049 \ ------------------------------\
15050 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
15051 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15052 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15053 \ ------------------------------\
15054 BIS.B #LCDVo,&LCDVo_DIR \
15055 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
15056 \ ------------------------------\
15057 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15058 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15059 \ ------------------------------\
15060 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15061 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15062 \ ******************************\
15064 \ ******************************\
15065 BIS.B #RC5,&IR_IE \ enable RC5_Int
15066 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15067 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15068 \ ******************************\
15069 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15070 \ ******************************\
15071 \ %01 0001 0100 \ TAxCTL
15072 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
15073 \ -- \ ID divided by 1
15074 \ -- \ MC MODE = up to TAxCCRn
15075 \ - \ TACLR clear timer count
15078 \ ------------------------------\
15079 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
15080 \ ------------------------------\
15082 \ --- \ TAIDEX pre divisor
15083 \ ------------------------------\
15084 \ %0000 0000 0000 0101 \ TAxCCR0
15085 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15086 \ ------------------------------\
15087 \ %0000 0000 0001 0000 \ TAxCCTL0
15088 \ - \ CAP capture/compare mode = compare
15091 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
15092 \ ------------------------------\
15093 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15094 \ ------------------------------\
15095 \ define LPM mode for ACCEPT \
15096 \ ------------------------------\
15097 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15098 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15099 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15100 \ ------------------------------\
15102 \ ------------------------------\
15103 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
15104 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
15105 \ ------------------------------\
15106 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
15107 \ ------------------------------\
15108 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
15109 \ CMP #2,Y \ Power_ON event
15110 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
15112 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
15114 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
15116 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
15118 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
15119 \ ------------------------------\
15121 \ ------------------------------\
15123 \ ------------------------------\
15124 #1000 20_US \ 1- wait 20 ms
15125 %011 TOP_LCD \ 2- send DB5=DB4=1
15126 #205 20_US \ 3- wait 4,1 ms
15127 %011 TOP_LCD \ 4- send again DB5=DB4=1
15128 #5 20_US \ 5- wait 0,1 ms
15129 %011 TOP_LCD \ 6- send again again DB5=DB4=1
15130 #2 20_US \ wait 40 us = LCD cycle
15131 %010 TOP_LCD \ 7- send DB5=1 DB4=0
15132 #2 20_US \ wait 40 us = LCD cycle
15133 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15134 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15135 LCD_CLEAR \ 10- "LCD_Clear"
15136 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15137 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15138 LCD_CLEAR \ 10- "LCD_Clear"
15139 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15140 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15141 CR ." I love you" \ display message on LCD
15142 ['] CR >BODY IS CR \ CR executes its default value
15143 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
15144 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15145 ABORT \ ...and end APP_INIT with ABORT, no return.
15148 \ ------------------------------\
15149 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
15150 \ ------------------------------\
15151 MOV #SLEEP,X \ replace default background process
15152 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
15153 MOV #WARM,X \ replace default WARM
15154 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
15155 MOV X,PC \ then execute it
15158 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
15162 CODE 20_US \ n -- n * 20 us
15163 BEGIN \ here we presume that LCD_TIM_IFG = 1...
15165 BIT #1,&LCD_TIM_CTL \ 3
15166 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15167 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15169 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15174 CODE TOP_LCD \ LCD Sample
15175 \ \ if write : %xxxxWWWW --
15176 \ \ if read : -- %0000RRRR
15177 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15178 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15179 0= IF \ write LCD bits pattern
15180 AND.B #LCD_DB,TOS \
15181 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15182 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15185 THEN \ read LCD bits pattern
15188 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15189 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15190 AND.B #LCD_DB,TOS \
15194 CODE LCD_WRC \ char -- Write Char
15195 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15197 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15198 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15199 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15200 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15201 COLON \ high level word starts here
15202 TOP_LCD 2 20_US \ write high nibble first
15206 CODE LCD_WRF \ func -- Write Fonction
15207 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15211 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
15212 : LCD_HOME $02 LCD_WRF 100 20_us ;
15214 \ [UNDEFINED] OR [IF]
15216 \ \ https://forth-standard.org/standard/core/OR
15217 \ \ C OR x1 x2 -- x3 logical OR
15225 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
15226 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
15227 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
15228 \ : LCD_FN_SET $20 OR LCD_WrF ;
15229 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
15230 \ : LCD_GOTO $80 OR LCD_WrF ;
15233 \ CODE LCD_RDS \ -- status Read Status
15234 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15235 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15236 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15237 \ COLON \ starts a FORTH word
15238 \ TOP_LCD 2 20_us \ -- %0000HHHH
15239 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
15240 \ HI2LO \ switch from FORTH to assembler
15241 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
15242 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
15243 \ MOV @RSP+,IP \ restore IP saved by COLON
15247 \ CODE LCD_RDC \ -- char Read Char
15248 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15253 \ ******************************\
15254 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15255 \ ******************************\
15256 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15257 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
15258 BIT.B #SW2,&SW2_IN \ test switch S2
15259 0= IF \ case of switch S2 pressed
15260 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15262 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
15265 BIT.B #SW1,&SW1_IN \ test switch S1 input
15266 0= IF \ case of Switch S1 pressed
15267 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15269 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15273 BW1 \ from quit on truncated RC5 message, repeated RC5 command
15277 \ ******************************\
15278 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15279 \ ******************************\
15280 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15281 \ ******************************\
15282 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15283 \ \ SMclock = 8|16|24 MHz
15284 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15285 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15286 \ \ SR(9)=new Toggle bit memory (ADD on)
15287 \ ******************************\
15288 \ RC5_FirstStartBitHalfCycle: \
15289 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15290 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15291 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
15292 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
15294 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
15295 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
15297 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
15298 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
15300 MOV #1778,X \ RC5_Period * 1us
15301 MOV #14,W \ count of loop
15303 \ ******************************\
15304 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
15305 \ ******************************\ |
15306 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15307 \ RC5_Compute_3/4_Period: \ |
15308 RRUM #1,X \ X=1/2 cycle |
15311 ADD X,Y \ Y=3/4 cycle
15312 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
15314 \ ******************************\
15315 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15316 \ ******************************\
15317 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15318 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
15319 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15320 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15321 SUB #1,W \ decrement count loop
15322 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
15323 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15324 0<> WHILE \ ----> out of loop ----+
15325 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15327 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
15328 CMP Y,X \ 1 | cycle time out of bound ?
15329 U>= IF \ 2 ^ | yes:
15330 BIC #$30,&RC5_TIM_CTL \ | | stop timer
15331 GOTO BW1 \ | | quit on truncated RC5 message
15333 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
15335 REPEAT \ ----> loop back --+ | with X = new RC5_period value
15336 \ ******************************\ |
15337 \ RC5_SampleEndOf: \ <---------------------+
15338 \ ******************************\
15339 BIC #$30,&RC5_TIM_CTL \ stop timer
15340 \ ******************************\
15341 \ RC5_ComputeNewRC5word \
15342 \ ******************************\
15343 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
15344 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
15345 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
15346 \ ******************************\
15347 \ RC5_ComputeC6bit \
15348 \ ******************************\
15349 BIT #BIT14,T \ test /C6 bit in T
15350 0= IF BIS #BIT6,X \ set C6 bit in X
15351 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
15352 \ ******************************\
15353 \ RC5_CommandByteIsDone \ -- BASE RC5_code
15354 \ ******************************\
15355 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15356 \ ******************************\
15357 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
15358 XOR @RSP,T \ (new XOR old) Toggle bits
15359 BIT #UF10,T \ repeated RC5_command ?
15360 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
15361 XOR #UF10,0(RSP) \ 5 toggle bit memory
15362 \ ******************************\
15363 \ Display IR_RC5 code \
15364 \ ******************************\
15365 SUB #8,PSP \ TOS -- x x x x TOS
15366 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
15367 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
15368 MOV #$10,&BASEADR \ set hexadecimal base
15369 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
15370 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
15371 LO2HI \ switch from assembler to FORTH
15372 LCD_CLEAR \ set LCD cursor at home
15373 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
15374 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
15375 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
15376 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
15377 HI2LO \ -- switch from FORTH to assembler
15378 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
15379 MOV @PSP+,TOS \ -- TOS
15383 \ ------------------------------\
15385 \ ------------------------------\
15387 \ ... \ insert here your background task
15390 CALL &RXON \ comment this line to disable TERMINAL
15392 \ ******************************\
15393 \ here start all interrupts \
15394 \ ******************************\
15395 \ here return all interrupts \
15396 \ ******************************\
15400 \ ------------------------------\
15401 CODE STOP \ stops multitasking, must to be used before downloading app
15402 \ ------------------------------\
15403 \ restore default action of primary DEFERred word SLEEP (assembly version)
15404 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
15405 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
15406 MOV X,-2(X) \ restore the default background
15407 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15408 ['] WARM >BODY IS WARM \ restore the default WARM
15410 ." RC5toLCD is removed. type START to restart"
15411 COLD \ performs reset to reset all interrupt vectors.
15414 \ ------------------------------\
15415 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
15416 \ ------------------------------\
15417 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15418 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15419 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15420 \ -- \ID input divider \ 10 = /4
15421 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15422 \ - \TBCLR TimerB Clear
15425 \ -------------------------------\
15426 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15427 \ -- \CM Capture Mode
15432 \ --- \OUTMOD \ 011 = set/reset
15438 \ -------------------------------\
15440 \ -------------------------------\
15442 \ ------------------------------\
15443 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15444 \ ------------------------------\
15445 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15446 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15447 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
15448 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15450 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
15451 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15453 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
15454 \ ------------------------------\
15455 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15456 \ ------------------------------\
15457 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
15458 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15459 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15460 \ ------------------------------\
15461 BIS.B #LCDVo,&LCDVo_DIR \
15462 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
15463 \ ------------------------------\
15464 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15465 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15466 \ ------------------------------\
15467 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15468 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15469 \ ******************************\
15471 \ ******************************\
15472 BIS.B #RC5,&IR_IE \ enable RC5_Int
15473 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15474 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15475 \ ******************************\
15476 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15477 \ ******************************\
15478 \ %01 0001 0100 \ TAxCTL
15479 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
15480 \ -- \ ID divided by 1
15481 \ -- \ MC MODE = up to TAxCCRn
15482 \ - \ TACLR clear timer count
15485 \ ------------------------------\
15486 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
15487 \ ------------------------------\
15489 \ --- \ TAIDEX pre divisor
15490 \ ------------------------------\
15491 \ %0000 0000 0000 0101 \ TAxCCR0
15492 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15493 \ ------------------------------\
15494 \ %0000 0000 0001 0000 \ TAxCCTL0
15495 \ - \ CAP capture/compare mode = compare
15498 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
15499 \ ------------------------------\
15500 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15501 \ ------------------------------\
15502 \ define LPM mode for ACCEPT \
15503 \ ------------------------------\
15504 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15505 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15506 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15507 \ ------------------------------\
15509 \ ------------------------------\
15510 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
15511 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
15512 \ ------------------------------\
15513 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
15514 \ ------------------------------\
15515 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
15516 \ CMP #2,Y \ Power_ON event
15517 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
15519 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
15521 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
15523 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
15525 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
15526 \ ------------------------------\
15528 \ ------------------------------\
15530 \ ------------------------------\
15531 #1000 20_US \ 1- wait 20 ms
15532 %011 TOP_LCD \ 2- send DB5=DB4=1
15533 #205 20_US \ 3- wait 4,1 ms
15534 %011 TOP_LCD \ 4- send again DB5=DB4=1
15535 #5 20_US \ 5- wait 0,1 ms
15536 %011 TOP_LCD \ 6- send again again DB5=DB4=1
15537 #2 20_US \ wait 40 us = LCD cycle
15538 %010 TOP_LCD \ 7- send DB5=1 DB4=0
15539 #2 20_US \ wait 40 us = LCD cycle
15540 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15541 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15542 LCD_CLEAR \ 10- "LCD_Clear"
15543 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15544 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15545 LCD_CLEAR \ 10- "LCD_Clear"
15546 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15547 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15548 CR ." I love you" \ display message on LCD
15549 ['] CR >BODY IS CR \ CR executes its default value
15550 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
15551 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15552 ABORT \ ...and end APP_INIT with ABORT, no return.
15555 \ ------------------------------\
15556 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
15557 \ ------------------------------\
15558 MOV #SLEEP,X \ replace default background process
15559 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
15560 MOV #WARM,X \ replace default WARM
15561 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
15562 MOV X,PC \ then execute it
15565 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
15569 CODE 20_US \ n -- n * 20 us
15570 BEGIN \ here we presume that LCD_TIM_IFG = 1...
15572 BIT #1,&LCD_TIM_CTL \ 3
15573 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15574 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15576 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15581 CODE TOP_LCD \ LCD Sample
15582 \ \ if write : %xxxxWWWW --
15583 \ \ if read : -- %0000RRRR
15584 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15585 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15586 0= IF \ write LCD bits pattern
15587 AND.B #LCD_DB,TOS \
15588 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15589 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15592 THEN \ read LCD bits pattern
15595 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15596 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15597 AND.B #LCD_DB,TOS \
15601 CODE LCD_WRC \ char -- Write Char
15602 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15604 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15605 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15606 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15607 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15608 COLON \ high level word starts here
15609 TOP_LCD 2 20_US \ write high nibble first
15613 CODE LCD_WRF \ func -- Write Fonction
15614 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15618 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
15619 : LCD_HOME $02 LCD_WRF 100 20_us ;
15621 \ [UNDEFINED] OR [IF]
15623 \ \ https://forth-standard.org/standard/core/OR
15624 \ \ C OR x1 x2 -- x3 logical OR
15632 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
15633 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
15634 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
15635 \ : LCD_FN_SET $20 OR LCD_WrF ;
15636 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
15637 \ : LCD_GOTO $80 OR LCD_WrF ;
15640 \ CODE LCD_RDS \ -- status Read Status
15641 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15642 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15643 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15644 \ COLON \ starts a FORTH word
15645 \ TOP_LCD 2 20_us \ -- %0000HHHH
15646 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
15647 \ HI2LO \ switch from FORTH to assembler
15648 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
15649 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
15650 \ MOV @RSP+,IP \ restore IP saved by COLON
15654 \ CODE LCD_RDC \ -- char Read Char
15655 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15660 \ ******************************\
15661 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15662 \ ******************************\
15663 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15664 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
15665 BIT.B #SW2,&SW2_IN \ test switch S2
15666 0= IF \ case of switch S2 pressed
15667 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15669 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
15672 BIT.B #SW1,&SW1_IN \ test switch S1 input
15673 0= IF \ case of Switch S1 pressed
15674 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15676 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15680 BW1 \ from quit on truncated RC5 message, repeated RC5 command
15684 \ ******************************\
15685 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15686 \ ******************************\
15687 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15688 \ ******************************\
15689 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15690 \ \ SMclock = 8|16|24 MHz
15691 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15692 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15693 \ \ SR(9)=new Toggle bit memory (ADD on)
15694 \ ******************************\
15695 \ RC5_FirstStartBitHalfCycle: \
15696 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15697 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15698 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
15699 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
15701 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
15702 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
15704 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
15705 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
15707 MOV #1778,X \ RC5_Period * 1us
15708 MOV #14,W \ count of loop
15710 \ ******************************\
15711 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
15712 \ ******************************\ |
15713 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15714 \ RC5_Compute_3/4_Period: \ |
15715 RRUM #1,X \ X=1/2 cycle |
15718 ADD X,Y \ Y=3/4 cycle
15719 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
15721 \ ******************************\
15722 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15723 \ ******************************\
15724 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15725 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
15726 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15727 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15728 SUB #1,W \ decrement count loop
15729 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
15730 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15731 0<> WHILE \ ----> out of loop ----+
15732 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15734 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
15735 CMP Y,X \ 1 | cycle time out of bound ?
15736 U>= IF \ 2 ^ | yes:
15737 BIC #$30,&RC5_TIM_CTL \ | | stop timer
15738 GOTO BW1 \ | | quit on truncated RC5 message
15740 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
15742 REPEAT \ ----> loop back --+ | with X = new RC5_period value
15743 \ ******************************\ |
15744 \ RC5_SampleEndOf: \ <---------------------+
15745 \ ******************************\
15746 BIC #$30,&RC5_TIM_CTL \ stop timer
15747 \ ******************************\
15748 \ RC5_ComputeNewRC5word \
15749 \ ******************************\
15750 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
15751 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
15752 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
15753 \ ******************************\
15754 \ RC5_ComputeC6bit \
15755 \ ******************************\
15756 BIT #BIT14,T \ test /C6 bit in T
15757 0= IF BIS #BIT6,X \ set C6 bit in X
15758 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
15759 \ ******************************\
15760 \ RC5_CommandByteIsDone \ -- BASE RC5_code
15761 \ ******************************\
15762 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15763 \ ******************************\
15764 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
15765 XOR @RSP,T \ (new XOR old) Toggle bits
15766 BIT #UF10,T \ repeated RC5_command ?
15767 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
15768 XOR #UF10,0(RSP) \ 5 toggle bit memory
15769 \ ******************************\
15770 \ Display IR_RC5 code \
15771 \ ******************************\
15772 SUB #8,PSP \ TOS -- x x x x TOS
15773 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
15774 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
15775 MOV #$10,&BASEADR \ set hexadecimal base
15776 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
15777 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
15778 LO2HI \ switch from assembler to FORTH
15779 LCD_CLEAR \ set LCD cursor at home
15780 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
15781 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
15782 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
15783 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
15784 HI2LO \ -- switch from FORTH to assembler
15785 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
15786 MOV @PSP+,TOS \ -- TOS
15790 \ ------------------------------\
15792 \ ------------------------------\
15794 \ ... \ insert here your background task
15797 CALL &RXON \ comment this line to disable TERMINAL
15799 \ ******************************\
15800 \ here start all interrupts \
15801 \ ******************************\
15802 \ here return all interrupts \
15803 \ ******************************\
15807 \ ------------------------------\
15808 CODE STOP \ stops multitasking, must to be used before downloading app
15809 \ ------------------------------\
15810 \ restore default action of primary DEFERred word SLEEP (assembly version)
15811 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
15812 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
15813 MOV X,-2(X) \ restore the default background
15814 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15815 ['] WARM >BODY IS WARM \ restore the default WARM
15817 ." RC5toLCD is removed. type START to restart"
15818 COLD \ performs reset to reset all interrupt vectors.
15821 \ ------------------------------\
15822 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
15823 \ ------------------------------\
15824 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15825 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15826 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15827 \ -- \ID input divider \ 10 = /4
15828 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15829 \ - \TBCLR TimerB Clear
15832 \ -------------------------------\
15833 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15834 \ -- \CM Capture Mode
15839 \ --- \OUTMOD \ 011 = set/reset
15845 \ -------------------------------\
15847 \ -------------------------------\
15849 \ ------------------------------\
15850 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15851 \ ------------------------------\
15852 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15853 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15854 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
15855 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15857 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
15858 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15860 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
15861 \ ------------------------------\
15862 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15863 \ ------------------------------\
15864 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
15865 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15866 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15867 \ ------------------------------\
15868 BIS.B #LCDVo,&LCDVo_DIR \
15869 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
15870 \ ------------------------------\
15871 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15872 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15873 \ ------------------------------\
15874 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15875 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15876 \ ******************************\
15878 \ ******************************\
15879 BIS.B #RC5,&IR_IE \ enable RC5_Int
15880 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15881 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15882 \ ******************************\
15883 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15884 \ ******************************\
15885 \ %01 0001 0100 \ TAxCTL
15886 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
15887 \ -- \ ID divided by 1
15888 \ -- \ MC MODE = up to TAxCCRn
15889 \ - \ TACLR clear timer count
15892 \ ------------------------------\
15893 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
15894 \ ------------------------------\
15896 \ --- \ TAIDEX pre divisor
15897 \ ------------------------------\
15898 \ %0000 0000 0000 0101 \ TAxCCR0
15899 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15900 \ ------------------------------\
15901 \ %0000 0000 0001 0000 \ TAxCCTL0
15902 \ - \ CAP capture/compare mode = compare
15905 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
15906 \ ------------------------------\
15907 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15908 \ ------------------------------\
15909 \ define LPM mode for ACCEPT \
15910 \ ------------------------------\
15911 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15912 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15913 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15914 \ ------------------------------\
15916 \ ------------------------------\
15917 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
15918 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
15919 \ ------------------------------\
15920 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
15921 \ ------------------------------\
15922 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
15923 \ CMP #2,Y \ Power_ON event
15924 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
15926 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
15928 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
15930 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
15932 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
15933 \ ------------------------------\
15935 \ ------------------------------\
15937 \ ------------------------------\
15938 #1000 20_US \ 1- wait 20 ms
15939 %011 TOP_LCD \ 2- send DB5=DB4=1
15940 #205 20_US \ 3- wait 4,1 ms
15941 %011 TOP_LCD \ 4- send again DB5=DB4=1
15942 #5 20_US \ 5- wait 0,1 ms
15943 %011 TOP_LCD \ 6- send again again DB5=DB4=1
15944 #2 20_US \ wait 40 us = LCD cycle
15945 %010 TOP_LCD \ 7- send DB5=1 DB4=0
15946 #2 20_US \ wait 40 us = LCD cycle
15947 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15948 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15949 LCD_CLEAR \ 10- "LCD_Clear"
15950 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15951 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15952 LCD_CLEAR \ 10- "LCD_Clear"
15953 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15954 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15955 CR ." I love you" \ display message on LCD
15956 ['] CR >BODY IS CR \ CR executes its default value
15957 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
15958 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15959 ABORT \ ...and end APP_INIT with ABORT, no return.
15962 \ ------------------------------\
15963 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
15964 \ ------------------------------\
15965 MOV #SLEEP,X \ replace default background process
15966 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
15967 MOV #WARM,X \ replace default WARM
15968 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
15969 MOV X,PC \ then execute it
15972 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
15976 CODE 20_US \ n -- n * 20 us
15977 BEGIN \ here we presume that LCD_TIM_IFG = 1...
15979 BIT #1,&LCD_TIM_CTL \ 3
15980 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15981 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15983 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15988 CODE TOP_LCD \ LCD Sample
15989 \ \ if write : %xxxxWWWW --
15990 \ \ if read : -- %0000RRRR
15991 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15992 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15993 0= IF \ write LCD bits pattern
15994 AND.B #LCD_DB,TOS \
15995 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15996 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15999 THEN \ read LCD bits pattern
16002 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16003 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16004 AND.B #LCD_DB,TOS \
16008 CODE LCD_WRC \ char -- Write Char
16009 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16011 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16012 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16013 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16014 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16015 COLON \ high level word starts here
16016 TOP_LCD 2 20_US \ write high nibble first
16020 CODE LCD_WRF \ func -- Write Fonction
16021 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16025 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16026 : LCD_HOME $02 LCD_WRF 100 20_us ;
16028 \ [UNDEFINED] OR [IF]
16030 \ \ https://forth-standard.org/standard/core/OR
16031 \ \ C OR x1 x2 -- x3 logical OR
16039 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
16040 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
16041 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
16042 \ : LCD_FN_SET $20 OR LCD_WrF ;
16043 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
16044 \ : LCD_GOTO $80 OR LCD_WrF ;
16047 \ CODE LCD_RDS \ -- status Read Status
16048 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16049 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16050 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16051 \ COLON \ starts a FORTH word
16052 \ TOP_LCD 2 20_us \ -- %0000HHHH
16053 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16054 \ HI2LO \ switch from FORTH to assembler
16055 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16056 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16057 \ MOV @RSP+,IP \ restore IP saved by COLON
16061 \ CODE LCD_RDC \ -- char Read Char
16062 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16067 \ ******************************\
16068 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16069 \ ******************************\
16070 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16071 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
16072 BIT.B #SW2,&SW2_IN \ test switch S2
16073 0= IF \ case of switch S2 pressed
16074 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16076 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
16079 BIT.B #SW1,&SW1_IN \ test switch S1 input
16080 0= IF \ case of Switch S1 pressed
16081 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16083 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16087 BW1 \ from quit on truncated RC5 message, repeated RC5 command
16091 \ ******************************\
16092 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16093 \ ******************************\
16094 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16095 \ ******************************\
16096 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16097 \ \ SMclock = 8|16|24 MHz
16098 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16099 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16100 \ \ SR(9)=new Toggle bit memory (ADD on)
16101 \ ******************************\
16102 \ RC5_FirstStartBitHalfCycle: \
16103 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16104 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16105 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
16106 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
16108 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
16109 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
16111 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
16112 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
16114 MOV #1778,X \ RC5_Period * 1us
16115 MOV #14,W \ count of loop
16117 \ ******************************\
16118 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
16119 \ ******************************\ |
16120 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16121 \ RC5_Compute_3/4_Period: \ |
16122 RRUM #1,X \ X=1/2 cycle |
16125 ADD X,Y \ Y=3/4 cycle
16126 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
16128 \ ******************************\
16129 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16130 \ ******************************\
16131 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16132 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
16133 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16134 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16135 SUB #1,W \ decrement count loop
16136 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
16137 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16138 0<> WHILE \ ----> out of loop ----+
16139 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16141 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
16142 CMP Y,X \ 1 | cycle time out of bound ?
16143 U>= IF \ 2 ^ | yes:
16144 BIC #$30,&RC5_TIM_CTL \ | | stop timer
16145 GOTO BW1 \ | | quit on truncated RC5 message
16147 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
16149 REPEAT \ ----> loop back --+ | with X = new RC5_period value
16150 \ ******************************\ |
16151 \ RC5_SampleEndOf: \ <---------------------+
16152 \ ******************************\
16153 BIC #$30,&RC5_TIM_CTL \ stop timer
16154 \ ******************************\
16155 \ RC5_ComputeNewRC5word \
16156 \ ******************************\
16157 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
16158 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
16159 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
16160 \ ******************************\
16161 \ RC5_ComputeC6bit \
16162 \ ******************************\
16163 BIT #BIT14,T \ test /C6 bit in T
16164 0= IF BIS #BIT6,X \ set C6 bit in X
16165 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
16166 \ ******************************\
16167 \ RC5_CommandByteIsDone \ -- BASE RC5_code
16168 \ ******************************\
16169 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16170 \ ******************************\
16171 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
16172 XOR @RSP,T \ (new XOR old) Toggle bits
16173 BIT #UF10,T \ repeated RC5_command ?
16174 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
16175 XOR #UF10,0(RSP) \ 5 toggle bit memory
16176 \ ******************************\
16177 \ Display IR_RC5 code \
16178 \ ******************************\
16179 SUB #8,PSP \ TOS -- x x x x TOS
16180 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
16181 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
16182 MOV #$10,&BASEADR \ set hexadecimal base
16183 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
16184 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
16185 LO2HI \ switch from assembler to FORTH
16186 LCD_CLEAR \ set LCD cursor at home
16187 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
16188 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
16189 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
16190 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
16191 HI2LO \ -- switch from FORTH to assembler
16192 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
16193 MOV @PSP+,TOS \ -- TOS
16197 \ ------------------------------\
16199 \ ------------------------------\
16201 \ ... \ insert here your background task
16204 CALL &RXON \ comment this line to disable TERMINAL
16206 \ ******************************\
16207 \ here start all interrupts \
16208 \ ******************************\
16209 \ here return all interrupts \
16210 \ ******************************\
16214 \ ------------------------------\
16215 CODE STOP \ stops multitasking, must to be used before downloading app
16216 \ ------------------------------\
16217 \ restore default action of primary DEFERred word SLEEP (assembly version)
16218 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
16219 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
16220 MOV X,-2(X) \ restore the default background
16221 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
16222 ['] WARM >BODY IS WARM \ restore the default WARM
16224 ." RC5toLCD is removed. type START to restart"
16225 COLD \ performs reset to reset all interrupt vectors.
16228 \ ------------------------------\
16229 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
16230 \ ------------------------------\
16231 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
16232 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16233 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16234 \ -- \ID input divider \ 10 = /4
16235 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
16236 \ - \TBCLR TimerB Clear
16239 \ -------------------------------\
16240 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16241 \ -- \CM Capture Mode
16246 \ --- \OUTMOD \ 011 = set/reset
16252 \ -------------------------------\
16254 \ -------------------------------\
16256 \ ------------------------------\
16257 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16258 \ ------------------------------\
16259 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16260 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16261 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
16262 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16264 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
16265 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16267 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
16268 \ ------------------------------\
16269 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16270 \ ------------------------------\
16271 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
16272 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16273 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16274 \ ------------------------------\
16275 BIS.B #LCDVo,&LCDVo_DIR \
16276 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
16277 \ ------------------------------\
16278 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16279 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16280 \ ------------------------------\
16281 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16282 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16283 \ ******************************\
16285 \ ******************************\
16286 BIS.B #RC5,&IR_IE \ enable RC5_Int
16287 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16288 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16289 \ ******************************\
16290 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16291 \ ******************************\
16292 \ %01 0001 0100 \ TAxCTL
16293 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
16294 \ -- \ ID divided by 1
16295 \ -- \ MC MODE = up to TAxCCRn
16296 \ - \ TACLR clear timer count
16299 \ ------------------------------\
16300 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
16301 \ ------------------------------\
16303 \ --- \ TAIDEX pre divisor
16304 \ ------------------------------\
16305 \ %0000 0000 0000 0101 \ TAxCCR0
16306 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16307 \ ------------------------------\
16308 \ %0000 0000 0001 0000 \ TAxCCTL0
16309 \ - \ CAP capture/compare mode = compare
16312 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
16313 \ ------------------------------\
16314 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16315 \ ------------------------------\
16316 \ define LPM mode for ACCEPT \
16317 \ ------------------------------\
16318 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16319 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16320 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16321 \ ------------------------------\
16323 \ ------------------------------\
16324 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
16325 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
16326 \ ------------------------------\
16327 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
16328 \ ------------------------------\
16329 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
16330 \ CMP #2,Y \ Power_ON event
16331 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
16333 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
16335 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
16337 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
16339 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
16340 \ ------------------------------\
16342 \ ------------------------------\
16344 \ ------------------------------\
16345 #1000 20_US \ 1- wait 20 ms
16346 %011 TOP_LCD \ 2- send DB5=DB4=1
16347 #205 20_US \ 3- wait 4,1 ms
16348 %011 TOP_LCD \ 4- send again DB5=DB4=1
16349 #5 20_US \ 5- wait 0,1 ms
16350 %011 TOP_LCD \ 6- send again again DB5=DB4=1
16351 #2 20_US \ wait 40 us = LCD cycle
16352 %010 TOP_LCD \ 7- send DB5=1 DB4=0
16353 #2 20_US \ wait 40 us = LCD cycle
16354 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16355 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16356 LCD_CLEAR \ 10- "LCD_Clear"
16357 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16358 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16359 LCD_CLEAR \ 10- "LCD_Clear"
16360 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16361 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16362 CR ." I love you" \ display message on LCD
16363 ['] CR >BODY IS CR \ CR executes its default value
16364 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
16365 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16366 ABORT \ ...and end APP_INIT with ABORT, no return.
16369 \ ------------------------------\
16370 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
16371 \ ------------------------------\
16372 MOV #SLEEP,X \ replace default background process
16373 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
16374 MOV #WARM,X \ replace default WARM
16375 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
16376 MOV X,PC \ then execute it
16379 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
16383 CODE 20_US \ n -- n * 20 us
16384 BEGIN \ here we presume that LCD_TIM_IFG = 1...
16386 BIT #1,&LCD_TIM_CTL \ 3
16387 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
16388 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
16390 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
16395 CODE TOP_LCD \ LCD Sample
16396 \ \ if write : %xxxxWWWW --
16397 \ \ if read : -- %0000RRRR
16398 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16399 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16400 0= IF \ write LCD bits pattern
16401 AND.B #LCD_DB,TOS \
16402 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16403 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16406 THEN \ read LCD bits pattern
16409 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16410 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16411 AND.B #LCD_DB,TOS \
16415 CODE LCD_WRC \ char -- Write Char
16416 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16418 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16419 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16420 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16421 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16422 COLON \ high level word starts here
16423 TOP_LCD 2 20_US \ write high nibble first
16427 CODE LCD_WRF \ func -- Write Fonction
16428 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16432 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16433 : LCD_HOME $02 LCD_WRF 100 20_us ;
16435 \ [UNDEFINED] OR [IF]
16437 \ \ https://forth-standard.org/standard/core/OR
16438 \ \ C OR x1 x2 -- x3 logical OR
16446 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
16447 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
16448 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
16449 \ : LCD_FN_SET $20 OR LCD_WrF ;
16450 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
16451 \ : LCD_GOTO $80 OR LCD_WrF ;
16454 \ CODE LCD_RDS \ -- status Read Status
16455 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16456 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16457 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16458 \ COLON \ starts a FORTH word
16459 \ TOP_LCD 2 20_us \ -- %0000HHHH
16460 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16461 \ HI2LO \ switch from FORTH to assembler
16462 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16463 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16464 \ MOV @RSP+,IP \ restore IP saved by COLON
16468 \ CODE LCD_RDC \ -- char Read Char
16469 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16474 \ ******************************\
16475 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16476 \ ******************************\
16477 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16478 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
16479 BIT.B #SW2,&SW2_IN \ test switch S2
16480 0= IF \ case of switch S2 pressed
16481 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16483 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
16486 BIT.B #SW1,&SW1_IN \ test switch S1 input
16487 0= IF \ case of Switch S1 pressed
16488 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16490 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16494 BW1 \ from quit on truncated RC5 message, repeated RC5 command
16498 \ ******************************\
16499 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16500 \ ******************************\
16501 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16502 \ ******************************\
16503 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16504 \ \ SMclock = 8|16|24 MHz
16505 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16506 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16507 \ \ SR(9)=new Toggle bit memory (ADD on)
16508 \ ******************************\
16509 \ RC5_FirstStartBitHalfCycle: \
16510 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16511 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16512 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
16513 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
16515 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
16516 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
16518 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
16519 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
16521 MOV #1778,X \ RC5_Period * 1us
16522 MOV #14,W \ count of loop
16524 \ ******************************\
16525 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
16526 \ ******************************\ |
16527 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16528 \ RC5_Compute_3/4_Period: \ |
16529 RRUM #1,X \ X=1/2 cycle |
16532 ADD X,Y \ Y=3/4 cycle
16533 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
16535 \ ******************************\
16536 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16537 \ ******************************\
16538 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16539 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
16540 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16541 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16542 SUB #1,W \ decrement count loop
16543 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
16544 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16545 0<> WHILE \ ----> out of loop ----+
16546 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16548 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
16549 CMP Y,X \ 1 | cycle time out of bound ?
16550 U>= IF \ 2 ^ | yes:
16551 BIC #$30,&RC5_TIM_CTL \ | | stop timer
16552 GOTO BW1 \ | | quit on truncated RC5 message
16554 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
16556 REPEAT \ ----> loop back --+ | with X = new RC5_period value
16557 \ ******************************\ |
16558 \ RC5_SampleEndOf: \ <---------------------+
16559 \ ******************************\
16560 BIC #$30,&RC5_TIM_CTL \ stop timer
16561 \ ******************************\
16562 \ RC5_ComputeNewRC5word \
16563 \ ******************************\
16564 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
16565 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
16566 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
16567 \ ******************************\
16568 \ RC5_ComputeC6bit \
16569 \ ******************************\
16570 BIT #BIT14,T \ test /C6 bit in T
16571 0= IF BIS #BIT6,X \ set C6 bit in X
16572 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
16573 \ ******************************\
16574 \ RC5_CommandByteIsDone \ -- BASE RC5_code
16575 \ ******************************\
16576 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16577 \ ******************************\
16578 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
16579 XOR @RSP,T \ (new XOR old) Toggle bits
16580 BIT #UF10,T \ repeated RC5_command ?
16581 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
16582 XOR #UF10,0(RSP) \ 5 toggle bit memory
16583 \ ******************************\
16584 \ Display IR_RC5 code \
16585 \ ******************************\
16586 SUB #8,PSP \ TOS -- x x x x TOS
16587 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
16588 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
16589 MOV #$10,&BASEADR \ set hexadecimal base
16590 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
16591 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
16592 LO2HI \ switch from assembler to FORTH
16593 LCD_CLEAR \ set LCD cursor at home
16594 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
16595 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
16596 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
16597 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
16598 HI2LO \ -- switch from FORTH to assembler
16599 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
16600 MOV @PSP+,TOS \ -- TOS
16604 \ ------------------------------\
16606 \ ------------------------------\
16608 \ ... \ insert here your background task
16611 CALL &RXON \ comment this line to disable TERMINAL
16613 \ ******************************\
16614 \ here start all interrupts \
16615 \ ******************************\
16616 \ here return all interrupts \
16617 \ ******************************\
16621 \ ------------------------------\
16622 CODE STOP \ stops multitasking, must to be used before downloading app
16623 \ ------------------------------\
16624 \ restore default action of primary DEFERred word SLEEP (assembly version)
16625 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
16626 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
16627 MOV X,-2(X) \ restore the default background
16628 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
16629 ['] WARM >BODY IS WARM \ restore the default WARM
16631 ." RC5toLCD is removed. type START to restart"
16632 COLD \ performs reset to reset all interrupt vectors.
16635 \ ------------------------------\
16636 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
16637 \ ------------------------------\
16638 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
16639 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16640 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16641 \ -- \ID input divider \ 10 = /4
16642 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
16643 \ - \TBCLR TimerB Clear
16646 \ -------------------------------\
16647 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16648 \ -- \CM Capture Mode
16653 \ --- \OUTMOD \ 011 = set/reset
16659 \ -------------------------------\
16661 \ -------------------------------\
16663 \ ------------------------------\
16664 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16665 \ ------------------------------\
16666 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16667 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16668 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
16669 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16671 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
16672 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16674 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
16675 \ ------------------------------\
16676 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16677 \ ------------------------------\
16678 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
16679 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16680 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16681 \ ------------------------------\
16682 BIS.B #LCDVo,&LCDVo_DIR \
16683 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
16684 \ ------------------------------\
16685 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16686 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16687 \ ------------------------------\
16688 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16689 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16690 \ ******************************\
16692 \ ******************************\
16693 BIS.B #RC5,&IR_IE \ enable RC5_Int
16694 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16695 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16696 \ ******************************\
16697 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16698 \ ******************************\
16699 \ %01 0001 0100 \ TAxCTL
16700 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
16701 \ -- \ ID divided by 1
16702 \ -- \ MC MODE = up to TAxCCRn
16703 \ - \ TACLR clear timer count
16706 \ ------------------------------\
16707 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
16708 \ ------------------------------\
16710 \ --- \ TAIDEX pre divisor
16711 \ ------------------------------\
16712 \ %0000 0000 0000 0101 \ TAxCCR0
16713 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16714 \ ------------------------------\
16715 \ %0000 0000 0001 0000 \ TAxCCTL0
16716 \ - \ CAP capture/compare mode = compare
16719 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
16720 \ ------------------------------\
16721 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16722 \ ------------------------------\
16723 \ define LPM mode for ACCEPT \
16724 \ ------------------------------\
16725 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16726 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16727 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16728 \ ------------------------------\
16730 \ ------------------------------\
16731 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
16732 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
16733 \ ------------------------------\
16734 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
16735 \ ------------------------------\
16736 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
16737 \ CMP #2,Y \ Power_ON event
16738 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
16740 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
16742 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
16744 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
16746 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
16747 \ ------------------------------\
16749 \ ------------------------------\
16751 \ ------------------------------\
16752 #1000 20_US \ 1- wait 20 ms
16753 %011 TOP_LCD \ 2- send DB5=DB4=1
16754 #205 20_US \ 3- wait 4,1 ms
16755 %011 TOP_LCD \ 4- send again DB5=DB4=1
16756 #5 20_US \ 5- wait 0,1 ms
16757 %011 TOP_LCD \ 6- send again again DB5=DB4=1
16758 #2 20_US \ wait 40 us = LCD cycle
16759 %010 TOP_LCD \ 7- send DB5=1 DB4=0
16760 #2 20_US \ wait 40 us = LCD cycle
16761 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16762 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16763 LCD_CLEAR \ 10- "LCD_Clear"
16764 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16765 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16766 LCD_CLEAR \ 10- "LCD_Clear"
16767 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16768 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16769 CR ." I love you" \ display message on LCD
16770 ['] CR >BODY IS CR \ CR executes its default value
16771 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
16772 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16773 ABORT \ ...and end APP_INIT with ABORT, no return.
16776 \ ------------------------------\
16777 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
16778 \ ------------------------------\
16779 MOV #SLEEP,X \ replace default background process
16780 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
16781 MOV #WARM,X \ replace default WARM
16782 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
16783 MOV X,PC \ then execute it
16786 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
16790 CODE 20_US \ n -- n * 20 us
16791 BEGIN \ here we presume that LCD_TIM_IFG = 1...
16793 BIT #1,&LCD_TIM_CTL \ 3
16794 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
16795 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
16797 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
16802 CODE TOP_LCD \ LCD Sample
16803 \ \ if write : %xxxxWWWW --
16804 \ \ if read : -- %0000RRRR
16805 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16806 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16807 0= IF \ write LCD bits pattern
16808 AND.B #LCD_DB,TOS \
16809 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16810 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16813 THEN \ read LCD bits pattern
16816 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16817 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16818 AND.B #LCD_DB,TOS \
16822 CODE LCD_WRC \ char -- Write Char
16823 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16825 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16826 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16827 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16828 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16829 COLON \ high level word starts here
16830 TOP_LCD 2 20_US \ write high nibble first
16834 CODE LCD_WRF \ func -- Write Fonction
16835 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16839 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16840 : LCD_HOME $02 LCD_WRF 100 20_us ;
16842 \ [UNDEFINED] OR [IF]
16844 \ \ https://forth-standard.org/standard/core/OR
16845 \ \ C OR x1 x2 -- x3 logical OR
16853 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
16854 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
16855 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
16856 \ : LCD_FN_SET $20 OR LCD_WrF ;
16857 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
16858 \ : LCD_GOTO $80 OR LCD_WrF ;
16861 \ CODE LCD_RDS \ -- status Read Status
16862 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16863 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16864 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16865 \ COLON \ starts a FORTH word
16866 \ TOP_LCD 2 20_us \ -- %0000HHHH
16867 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16868 \ HI2LO \ switch from FORTH to assembler
16869 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16870 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16871 \ MOV @RSP+,IP \ restore IP saved by COLON
16875 \ CODE LCD_RDC \ -- char Read Char
16876 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16881 \ ******************************\
16882 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16883 \ ******************************\
16884 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16885 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
16886 BIT.B #SW2,&SW2_IN \ test switch S2
16887 0= IF \ case of switch S2 pressed
16888 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16890 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
16893 BIT.B #SW1,&SW1_IN \ test switch S1 input
16894 0= IF \ case of Switch S1 pressed
16895 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16897 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16901 BW1 \ from quit on truncated RC5 message, repeated RC5 command
16905 \ ******************************\
16906 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16907 \ ******************************\
16908 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16909 \ ******************************\
16910 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16911 \ \ SMclock = 8|16|24 MHz
16912 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16913 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16914 \ \ SR(9)=new Toggle bit memory (ADD on)
16915 \ ******************************\
16916 \ RC5_FirstStartBitHalfCycle: \
16917 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16918 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16919 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
16920 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
16922 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
16923 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
16925 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
16926 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
16928 MOV #1778,X \ RC5_Period * 1us
16929 MOV #14,W \ count of loop
16931 \ ******************************\
16932 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
16933 \ ******************************\ |
16934 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16935 \ RC5_Compute_3/4_Period: \ |
16936 RRUM #1,X \ X=1/2 cycle |
16939 ADD X,Y \ Y=3/4 cycle
16940 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
16942 \ ******************************\
16943 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16944 \ ******************************\
16945 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16946 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
16947 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16948 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16949 SUB #1,W \ decrement count loop
16950 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
16951 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16952 0<> WHILE \ ----> out of loop ----+
16953 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16955 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
16956 CMP Y,X \ 1 | cycle time out of bound ?
16957 U>= IF \ 2 ^ | yes:
16958 BIC #$30,&RC5_TIM_CTL \ | | stop timer
16959 GOTO BW1 \ | | quit on truncated RC5 message
16961 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
16963 REPEAT \ ----> loop back --+ | with X = new RC5_period value
16964 \ ******************************\ |
16965 \ RC5_SampleEndOf: \ <---------------------+
16966 \ ******************************\
16967 BIC #$30,&RC5_TIM_CTL \ stop timer
16968 \ ******************************\
16969 \ RC5_ComputeNewRC5word \
16970 \ ******************************\
16971 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
16972 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
16973 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
16974 \ ******************************\
16975 \ RC5_ComputeC6bit \
16976 \ ******************************\
16977 BIT #BIT14,T \ test /C6 bit in T
16978 0= IF BIS #BIT6,X \ set C6 bit in X
16979 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
16980 \ ******************************\
16981 \ RC5_CommandByteIsDone \ -- BASE RC5_code
16982 \ ******************************\
16983 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16984 \ ******************************\
16985 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
16986 XOR @RSP,T \ (new XOR old) Toggle bits
16987 BIT #UF10,T \ repeated RC5_command ?
16988 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
16989 XOR #UF10,0(RSP) \ 5 toggle bit memory
16990 \ ******************************\
16991 \ Display IR_RC5 code \
16992 \ ******************************\
16993 SUB #8,PSP \ TOS -- x x x x TOS
16994 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
16995 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
16996 MOV #$10,&BASEADR \ set hexadecimal base
16997 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
16998 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
16999 LO2HI \ switch from assembler to FORTH
17000 LCD_CLEAR \ set LCD cursor at home
17001 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17002 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17003 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17004 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17005 HI2LO \ -- switch from FORTH to assembler
17006 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17007 MOV @PSP+,TOS \ -- TOS
17011 \ ------------------------------\
17013 \ ------------------------------\
17015 \ ... \ insert here your background task
17018 CALL &RXON \ comment this line to disable TERMINAL
17020 \ ******************************\
17021 \ here start all interrupts \
17022 \ ******************************\
17023 \ here return all interrupts \
17024 \ ******************************\
17028 \ ------------------------------\
17029 CODE STOP \ stops multitasking, must to be used before downloading app
17030 \ ------------------------------\
17031 \ restore default action of primary DEFERred word SLEEP (assembly version)
17032 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
17033 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17034 MOV X,-2(X) \ restore the default background
17035 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17036 ['] WARM >BODY IS WARM \ restore the default WARM
17038 ." RC5toLCD is removed. type START to restart"
17039 COLD \ performs reset to reset all interrupt vectors.
17042 \ ------------------------------\
17043 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
17044 \ ------------------------------\
17045 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
17046 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17047 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17048 \ -- \ID input divider \ 10 = /4
17049 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17050 \ - \TBCLR TimerB Clear
17053 \ -------------------------------\
17054 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17055 \ -- \CM Capture Mode
17060 \ --- \OUTMOD \ 011 = set/reset
17066 \ -------------------------------\
17068 \ -------------------------------\
17070 \ ------------------------------\
17071 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17072 \ ------------------------------\
17073 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17074 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17075 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
17076 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17078 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
17079 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17081 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
17082 \ ------------------------------\
17083 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17084 \ ------------------------------\
17085 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
17086 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17087 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17088 \ ------------------------------\
17089 BIS.B #LCDVo,&LCDVo_DIR \
17090 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
17091 \ ------------------------------\
17092 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17093 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17094 \ ------------------------------\
17095 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17096 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17097 \ ******************************\
17099 \ ******************************\
17100 BIS.B #RC5,&IR_IE \ enable RC5_Int
17101 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17102 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17103 \ ******************************\
17104 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17105 \ ******************************\
17106 \ %01 0001 0100 \ TAxCTL
17107 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
17108 \ -- \ ID divided by 1
17109 \ -- \ MC MODE = up to TAxCCRn
17110 \ - \ TACLR clear timer count
17113 \ ------------------------------\
17114 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
17115 \ ------------------------------\
17117 \ --- \ TAIDEX pre divisor
17118 \ ------------------------------\
17119 \ %0000 0000 0000 0101 \ TAxCCR0
17120 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17121 \ ------------------------------\
17122 \ %0000 0000 0001 0000 \ TAxCCTL0
17123 \ - \ CAP capture/compare mode = compare
17126 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17127 \ ------------------------------\
17128 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17129 \ ------------------------------\
17130 \ define LPM mode for ACCEPT \
17131 \ ------------------------------\
17132 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17133 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17134 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17135 \ ------------------------------\
17137 \ ------------------------------\
17138 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
17139 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17140 \ ------------------------------\
17141 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17142 \ ------------------------------\
17143 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
17144 \ CMP #2,Y \ Power_ON event
17145 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
17147 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
17149 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
17151 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
17153 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
17154 \ ------------------------------\
17156 \ ------------------------------\
17158 \ ------------------------------\
17159 #1000 20_US \ 1- wait 20 ms
17160 %011 TOP_LCD \ 2- send DB5=DB4=1
17161 #205 20_US \ 3- wait 4,1 ms
17162 %011 TOP_LCD \ 4- send again DB5=DB4=1
17163 #5 20_US \ 5- wait 0,1 ms
17164 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17165 #2 20_US \ wait 40 us = LCD cycle
17166 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17167 #2 20_US \ wait 40 us = LCD cycle
17168 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17169 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17170 LCD_CLEAR \ 10- "LCD_Clear"
17171 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17172 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17173 LCD_CLEAR \ 10- "LCD_Clear"
17174 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17175 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17176 CR ." I love you" \ display message on LCD
17177 ['] CR >BODY IS CR \ CR executes its default value
17178 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17179 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17180 ABORT \ ...and end APP_INIT with ABORT, no return.
17183 \ ------------------------------\
17184 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
17185 \ ------------------------------\
17186 MOV #SLEEP,X \ replace default background process
17187 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
17188 MOV #WARM,X \ replace default WARM
17189 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
17190 MOV X,PC \ then execute it
17193 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
17197 CODE 20_US \ n -- n * 20 us
17198 BEGIN \ here we presume that LCD_TIM_IFG = 1...
17200 BIT #1,&LCD_TIM_CTL \ 3
17201 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
17202 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
17204 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
17209 CODE TOP_LCD \ LCD Sample
17210 \ \ if write : %xxxxWWWW --
17211 \ \ if read : -- %0000RRRR
17212 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17213 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17214 0= IF \ write LCD bits pattern
17215 AND.B #LCD_DB,TOS \
17216 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17217 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17220 THEN \ read LCD bits pattern
17223 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17224 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17225 AND.B #LCD_DB,TOS \
17229 CODE LCD_WRC \ char -- Write Char
17230 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17232 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
17233 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
17234 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17235 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17236 COLON \ high level word starts here
17237 TOP_LCD 2 20_US \ write high nibble first
17241 CODE LCD_WRF \ func -- Write Fonction
17242 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17246 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
17247 : LCD_HOME $02 LCD_WRF 100 20_us ;
17249 \ [UNDEFINED] OR [IF]
17251 \ \ https://forth-standard.org/standard/core/OR
17252 \ \ C OR x1 x2 -- x3 logical OR
17260 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
17261 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
17262 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
17263 \ : LCD_FN_SET $20 OR LCD_WrF ;
17264 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
17265 \ : LCD_GOTO $80 OR LCD_WrF ;
17268 \ CODE LCD_RDS \ -- status Read Status
17269 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17270 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17271 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17272 \ COLON \ starts a FORTH word
17273 \ TOP_LCD 2 20_us \ -- %0000HHHH
17274 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
17275 \ HI2LO \ switch from FORTH to assembler
17276 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
17277 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
17278 \ MOV @RSP+,IP \ restore IP saved by COLON
17282 \ CODE LCD_RDC \ -- char Read Char
17283 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17288 \ ******************************\
17289 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17290 \ ******************************\
17291 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17292 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
17293 BIT.B #SW2,&SW2_IN \ test switch S2
17294 0= IF \ case of switch S2 pressed
17295 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17297 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
17300 BIT.B #SW1,&SW1_IN \ test switch S1 input
17301 0= IF \ case of Switch S1 pressed
17302 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17304 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17308 BW1 \ from quit on truncated RC5 message, repeated RC5 command
17312 \ ******************************\
17313 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17314 \ ******************************\
17315 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17316 \ ******************************\
17317 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17318 \ \ SMclock = 8|16|24 MHz
17319 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17320 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17321 \ \ SR(9)=new Toggle bit memory (ADD on)
17322 \ ******************************\
17323 \ RC5_FirstStartBitHalfCycle: \
17324 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17325 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17326 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
17327 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
17329 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
17330 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
17332 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
17333 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
17335 MOV #1778,X \ RC5_Period * 1us
17336 MOV #14,W \ count of loop
17338 \ ******************************\
17339 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
17340 \ ******************************\ |
17341 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17342 \ RC5_Compute_3/4_Period: \ |
17343 RRUM #1,X \ X=1/2 cycle |
17346 ADD X,Y \ Y=3/4 cycle
17347 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
17349 \ ******************************\
17350 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17351 \ ******************************\
17352 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17353 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
17354 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17355 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17356 SUB #1,W \ decrement count loop
17357 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
17358 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17359 0<> WHILE \ ----> out of loop ----+
17360 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17362 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
17363 CMP Y,X \ 1 | cycle time out of bound ?
17364 U>= IF \ 2 ^ | yes:
17365 BIC #$30,&RC5_TIM_CTL \ | | stop timer
17366 GOTO BW1 \ | | quit on truncated RC5 message
17368 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
17370 REPEAT \ ----> loop back --+ | with X = new RC5_period value
17371 \ ******************************\ |
17372 \ RC5_SampleEndOf: \ <---------------------+
17373 \ ******************************\
17374 BIC #$30,&RC5_TIM_CTL \ stop timer
17375 \ ******************************\
17376 \ RC5_ComputeNewRC5word \
17377 \ ******************************\
17378 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
17379 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
17380 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
17381 \ ******************************\
17382 \ RC5_ComputeC6bit \
17383 \ ******************************\
17384 BIT #BIT14,T \ test /C6 bit in T
17385 0= IF BIS #BIT6,X \ set C6 bit in X
17386 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
17387 \ ******************************\
17388 \ RC5_CommandByteIsDone \ -- BASE RC5_code
17389 \ ******************************\
17390 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17391 \ ******************************\
17392 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
17393 XOR @RSP,T \ (new XOR old) Toggle bits
17394 BIT #UF10,T \ repeated RC5_command ?
17395 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
17396 XOR #UF10,0(RSP) \ 5 toggle bit memory
17397 \ ******************************\
17398 \ Display IR_RC5 code \
17399 \ ******************************\
17400 SUB #8,PSP \ TOS -- x x x x TOS
17401 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
17402 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
17403 MOV #$10,&BASEADR \ set hexadecimal base
17404 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
17405 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
17406 LO2HI \ switch from assembler to FORTH
17407 LCD_CLEAR \ set LCD cursor at home
17408 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17409 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17410 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17411 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17412 HI2LO \ -- switch from FORTH to assembler
17413 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17414 MOV @PSP+,TOS \ -- TOS
17418 \ ------------------------------\
17420 \ ------------------------------\
17422 \ ... \ insert here your background task
17425 CALL &RXON \ comment this line to disable TERMINAL
17427 \ ******************************\
17428 \ here start all interrupts \
17429 \ ******************************\
17430 \ here return all interrupts \
17431 \ ******************************\
17435 \ ------------------------------\
17436 CODE STOP \ stops multitasking, must to be used before downloading app
17437 \ ------------------------------\
17438 \ restore default action of primary DEFERred word SLEEP (assembly version)
17439 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
17440 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17441 MOV X,-2(X) \ restore the default background
17442 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17443 ['] WARM >BODY IS WARM \ restore the default WARM
17445 ." RC5toLCD is removed. type START to restart"
17446 COLD \ performs reset to reset all interrupt vectors.
17449 \ ------------------------------\
17450 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
17451 \ ------------------------------\
17452 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
17453 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17454 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17455 \ -- \ID input divider \ 10 = /4
17456 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17457 \ - \TBCLR TimerB Clear
17460 \ -------------------------------\
17461 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17462 \ -- \CM Capture Mode
17467 \ --- \OUTMOD \ 011 = set/reset
17473 \ -------------------------------\
17475 \ -------------------------------\
17477 \ ------------------------------\
17478 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17479 \ ------------------------------\
17480 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17481 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17482 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
17483 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17485 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
17486 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17488 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
17489 \ ------------------------------\
17490 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17491 \ ------------------------------\
17492 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
17493 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17494 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17495 \ ------------------------------\
17496 BIS.B #LCDVo,&LCDVo_DIR \
17497 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
17498 \ ------------------------------\
17499 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17500 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17501 \ ------------------------------\
17502 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17503 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17504 \ ******************************\
17506 \ ******************************\
17507 BIS.B #RC5,&IR_IE \ enable RC5_Int
17508 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17509 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17510 \ ******************************\
17511 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17512 \ ******************************\
17513 \ %01 0001 0100 \ TAxCTL
17514 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
17515 \ -- \ ID divided by 1
17516 \ -- \ MC MODE = up to TAxCCRn
17517 \ - \ TACLR clear timer count
17520 \ ------------------------------\
17521 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
17522 \ ------------------------------\
17524 \ --- \ TAIDEX pre divisor
17525 \ ------------------------------\
17526 \ %0000 0000 0000 0101 \ TAxCCR0
17527 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17528 \ ------------------------------\
17529 \ %0000 0000 0001 0000 \ TAxCCTL0
17530 \ - \ CAP capture/compare mode = compare
17533 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17534 \ ------------------------------\
17535 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17536 \ ------------------------------\
17537 \ define LPM mode for ACCEPT \
17538 \ ------------------------------\
17539 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17540 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17541 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17542 \ ------------------------------\
17544 \ ------------------------------\
17545 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
17546 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17547 \ ------------------------------\
17548 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17549 \ ------------------------------\
17550 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
17551 \ CMP #2,Y \ Power_ON event
17552 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
17554 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
17556 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
17558 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
17560 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
17561 \ ------------------------------\
17563 \ ------------------------------\
17565 \ ------------------------------\
17566 #1000 20_US \ 1- wait 20 ms
17567 %011 TOP_LCD \ 2- send DB5=DB4=1
17568 #205 20_US \ 3- wait 4,1 ms
17569 %011 TOP_LCD \ 4- send again DB5=DB4=1
17570 #5 20_US \ 5- wait 0,1 ms
17571 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17572 #2 20_US \ wait 40 us = LCD cycle
17573 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17574 #2 20_US \ wait 40 us = LCD cycle
17575 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17576 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17577 LCD_CLEAR \ 10- "LCD_Clear"
17578 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17579 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17580 LCD_CLEAR \ 10- "LCD_Clear"
17581 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17582 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17583 CR ." I love you" \ display message on LCD
17584 ['] CR >BODY IS CR \ CR executes its default value
17585 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17586 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17587 ABORT \ ...and end APP_INIT with ABORT, no return.
17590 \ ------------------------------\
17591 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
17592 \ ------------------------------\
17593 MOV #SLEEP,X \ replace default background process
17594 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
17595 MOV #WARM,X \ replace default WARM
17596 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
17597 MOV X,PC \ then execute it
17600 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
17604 CODE 20_US \ n -- n * 20 us
17605 BEGIN \ here we presume that LCD_TIM_IFG = 1...
17607 BIT #1,&LCD_TIM_CTL \ 3
17608 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
17609 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
17611 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
17616 CODE TOP_LCD \ LCD Sample
17617 \ \ if write : %xxxxWWWW --
17618 \ \ if read : -- %0000RRRR
17619 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17620 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17621 0= IF \ write LCD bits pattern
17622 AND.B #LCD_DB,TOS \
17623 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17624 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17627 THEN \ read LCD bits pattern
17630 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17631 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17632 AND.B #LCD_DB,TOS \
17636 CODE LCD_WRC \ char -- Write Char
17637 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17639 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
17640 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
17641 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17642 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17643 COLON \ high level word starts here
17644 TOP_LCD 2 20_US \ write high nibble first
17648 CODE LCD_WRF \ func -- Write Fonction
17649 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17653 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
17654 : LCD_HOME $02 LCD_WRF 100 20_us ;
17656 \ [UNDEFINED] OR [IF]
17658 \ \ https://forth-standard.org/standard/core/OR
17659 \ \ C OR x1 x2 -- x3 logical OR
17667 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
17668 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
17669 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
17670 \ : LCD_FN_SET $20 OR LCD_WrF ;
17671 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
17672 \ : LCD_GOTO $80 OR LCD_WrF ;
17675 \ CODE LCD_RDS \ -- status Read Status
17676 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17677 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17678 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17679 \ COLON \ starts a FORTH word
17680 \ TOP_LCD 2 20_us \ -- %0000HHHH
17681 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
17682 \ HI2LO \ switch from FORTH to assembler
17683 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
17684 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
17685 \ MOV @RSP+,IP \ restore IP saved by COLON
17689 \ CODE LCD_RDC \ -- char Read Char
17690 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17695 \ ******************************\
17696 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17697 \ ******************************\
17698 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17699 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
17700 BIT.B #SW2,&SW2_IN \ test switch S2
17701 0= IF \ case of switch S2 pressed
17702 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17704 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
17707 BIT.B #SW1,&SW1_IN \ test switch S1 input
17708 0= IF \ case of Switch S1 pressed
17709 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17711 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17715 BW1 \ from quit on truncated RC5 message, repeated RC5 command
17719 \ ******************************\
17720 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17721 \ ******************************\
17722 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17723 \ ******************************\
17724 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17725 \ \ SMclock = 8|16|24 MHz
17726 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17727 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17728 \ \ SR(9)=new Toggle bit memory (ADD on)
17729 \ ******************************\
17730 \ RC5_FirstStartBitHalfCycle: \
17731 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17732 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17733 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
17734 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
17736 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
17737 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
17739 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
17740 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
17742 MOV #1778,X \ RC5_Period * 1us
17743 MOV #14,W \ count of loop
17745 \ ******************************\
17746 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
17747 \ ******************************\ |
17748 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17749 \ RC5_Compute_3/4_Period: \ |
17750 RRUM #1,X \ X=1/2 cycle |
17753 ADD X,Y \ Y=3/4 cycle
17754 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
17756 \ ******************************\
17757 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17758 \ ******************************\
17759 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17760 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
17761 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17762 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17763 SUB #1,W \ decrement count loop
17764 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
17765 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17766 0<> WHILE \ ----> out of loop ----+
17767 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17769 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
17770 CMP Y,X \ 1 | cycle time out of bound ?
17771 U>= IF \ 2 ^ | yes:
17772 BIC #$30,&RC5_TIM_CTL \ | | stop timer
17773 GOTO BW1 \ | | quit on truncated RC5 message
17775 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
17777 REPEAT \ ----> loop back --+ | with X = new RC5_period value
17778 \ ******************************\ |
17779 \ RC5_SampleEndOf: \ <---------------------+
17780 \ ******************************\
17781 BIC #$30,&RC5_TIM_CTL \ stop timer
17782 \ ******************************\
17783 \ RC5_ComputeNewRC5word \
17784 \ ******************************\
17785 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
17786 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
17787 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
17788 \ ******************************\
17789 \ RC5_ComputeC6bit \
17790 \ ******************************\
17791 BIT #BIT14,T \ test /C6 bit in T
17792 0= IF BIS #BIT6,X \ set C6 bit in X
17793 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
17794 \ ******************************\
17795 \ RC5_CommandByteIsDone \ -- BASE RC5_code
17796 \ ******************************\
17797 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17798 \ ******************************\
17799 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
17800 XOR @RSP,T \ (new XOR old) Toggle bits
17801 BIT #UF10,T \ repeated RC5_command ?
17802 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
17803 XOR #UF10,0(RSP) \ 5 toggle bit memory
17804 \ ******************************\
17805 \ Display IR_RC5 code \
17806 \ ******************************\
17807 SUB #8,PSP \ TOS -- x x x x TOS
17808 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
17809 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
17810 MOV #$10,&BASEADR \ set hexadecimal base
17811 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
17812 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
17813 LO2HI \ switch from assembler to FORTH
17814 LCD_CLEAR \ set LCD cursor at home
17815 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17816 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17817 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17818 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17819 HI2LO \ -- switch from FORTH to assembler
17820 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17821 MOV @PSP+,TOS \ -- TOS
17825 \ ------------------------------\
17827 \ ------------------------------\
17829 \ ... \ insert here your background task
17832 CALL &RXON \ comment this line to disable TERMINAL
17834 \ ******************************\
17835 \ here start all interrupts \
17836 \ ******************************\
17837 \ here return all interrupts \
17838 \ ******************************\
17842 \ ------------------------------\
17843 CODE STOP \ stops multitasking, must to be used before downloading app
17844 \ ------------------------------\
17845 \ restore default action of primary DEFERred word SLEEP (assembly version)
17846 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
17847 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17848 MOV X,-2(X) \ restore the default background
17849 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17850 ['] WARM >BODY IS WARM \ restore the default WARM
17852 ." RC5toLCD is removed. type START to restart"
17853 COLD \ performs reset to reset all interrupt vectors.
17856 \ ------------------------------\
17857 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
17858 \ ------------------------------\
17859 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
17860 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17861 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17862 \ -- \ID input divider \ 10 = /4
17863 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17864 \ - \TBCLR TimerB Clear
17867 \ -------------------------------\
17868 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17869 \ -- \CM Capture Mode
17874 \ --- \OUTMOD \ 011 = set/reset
17880 \ -------------------------------\
17882 \ -------------------------------\
17884 \ ------------------------------\
17885 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17886 \ ------------------------------\
17887 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17888 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17889 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
17890 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17892 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
17893 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17895 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
17896 \ ------------------------------\
17897 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17898 \ ------------------------------\
17899 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
17900 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17901 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17902 \ ------------------------------\
17903 BIS.B #LCDVo,&LCDVo_DIR \
17904 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
17905 \ ------------------------------\
17906 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17907 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17908 \ ------------------------------\
17909 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17910 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17911 \ ******************************\
17913 \ ******************************\
17914 BIS.B #RC5,&IR_IE \ enable RC5_Int
17915 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17916 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17917 \ ******************************\
17918 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17919 \ ******************************\
17920 \ %01 0001 0100 \ TAxCTL
17921 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
17922 \ -- \ ID divided by 1
17923 \ -- \ MC MODE = up to TAxCCRn
17924 \ - \ TACLR clear timer count
17927 \ ------------------------------\
17928 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
17929 \ ------------------------------\
17931 \ --- \ TAIDEX pre divisor
17932 \ ------------------------------\
17933 \ %0000 0000 0000 0101 \ TAxCCR0
17934 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17935 \ ------------------------------\
17936 \ %0000 0000 0001 0000 \ TAxCCTL0
17937 \ - \ CAP capture/compare mode = compare
17940 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17941 \ ------------------------------\
17942 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17943 \ ------------------------------\
17944 \ define LPM mode for ACCEPT \
17945 \ ------------------------------\
17946 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17947 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17948 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17949 \ ------------------------------\
17951 \ ------------------------------\
17952 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
17953 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17954 \ ------------------------------\
17955 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17956 \ ------------------------------\
17957 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
17958 \ CMP #2,Y \ Power_ON event
17959 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
17961 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
17963 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
17965 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
17967 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
17968 \ ------------------------------\
17970 \ ------------------------------\
17972 \ ------------------------------\
17973 #1000 20_US \ 1- wait 20 ms
17974 %011 TOP_LCD \ 2- send DB5=DB4=1
17975 #205 20_US \ 3- wait 4,1 ms
17976 %011 TOP_LCD \ 4- send again DB5=DB4=1
17977 #5 20_US \ 5- wait 0,1 ms
17978 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17979 #2 20_US \ wait 40 us = LCD cycle
17980 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17981 #2 20_US \ wait 40 us = LCD cycle
17982 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17983 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17984 LCD_CLEAR \ 10- "LCD_Clear"
17985 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17986 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17987 LCD_CLEAR \ 10- "LCD_Clear"
17988 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17989 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17990 CR ." I love you" \ display message on LCD
17991 ['] CR >BODY IS CR \ CR executes its default value
17992 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17993 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17994 ABORT \ ...and end APP_INIT with ABORT, no return.
17997 \ ------------------------------\
17998 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
17999 \ ------------------------------\
18000 MOV #SLEEP,X \ replace default background process
18001 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
18002 MOV #WARM,X \ replace default WARM
18003 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
18004 MOV X,PC \ then execute it
18007 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
18011 CODE 20_US \ n -- n * 20 us
18012 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18014 BIT #1,&LCD_TIM_CTL \ 3
18015 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18016 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18018 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18023 CODE TOP_LCD \ LCD Sample
18024 \ \ if write : %xxxxWWWW --
18025 \ \ if read : -- %0000RRRR
18026 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18027 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18028 0= IF \ write LCD bits pattern
18029 AND.B #LCD_DB,TOS \
18030 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18031 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18034 THEN \ read LCD bits pattern
18037 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18038 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18039 AND.B #LCD_DB,TOS \
18043 CODE LCD_WRC \ char -- Write Char
18044 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18046 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18047 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18048 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18049 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18050 COLON \ high level word starts here
18051 TOP_LCD 2 20_US \ write high nibble first
18055 CODE LCD_WRF \ func -- Write Fonction
18056 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18060 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18061 : LCD_HOME $02 LCD_WRF 100 20_us ;
18063 \ [UNDEFINED] OR [IF]
18065 \ \ https://forth-standard.org/standard/core/OR
18066 \ \ C OR x1 x2 -- x3 logical OR
18074 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18075 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18076 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18077 \ : LCD_FN_SET $20 OR LCD_WrF ;
18078 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18079 \ : LCD_GOTO $80 OR LCD_WrF ;
18082 \ CODE LCD_RDS \ -- status Read Status
18083 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18084 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18085 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18086 \ COLON \ starts a FORTH word
18087 \ TOP_LCD 2 20_us \ -- %0000HHHH
18088 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18089 \ HI2LO \ switch from FORTH to assembler
18090 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18091 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18092 \ MOV @RSP+,IP \ restore IP saved by COLON
18096 \ CODE LCD_RDC \ -- char Read Char
18097 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18102 \ ******************************\
18103 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18104 \ ******************************\
18105 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18106 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18107 BIT.B #SW2,&SW2_IN \ test switch S2
18108 0= IF \ case of switch S2 pressed
18109 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18111 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18114 BIT.B #SW1,&SW1_IN \ test switch S1 input
18115 0= IF \ case of Switch S1 pressed
18116 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18118 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18122 BW1 \ from quit on truncated RC5 message, repeated RC5 command
18126 \ ******************************\
18127 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18128 \ ******************************\
18129 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18130 \ ******************************\
18131 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18132 \ \ SMclock = 8|16|24 MHz
18133 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18134 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18135 \ \ SR(9)=new Toggle bit memory (ADD on)
18136 \ ******************************\
18137 \ RC5_FirstStartBitHalfCycle: \
18138 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18139 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18140 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18141 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18143 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18144 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18146 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18147 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18149 MOV #1778,X \ RC5_Period * 1us
18150 MOV #14,W \ count of loop
18152 \ ******************************\
18153 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18154 \ ******************************\ |
18155 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18156 \ RC5_Compute_3/4_Period: \ |
18157 RRUM #1,X \ X=1/2 cycle |
18160 ADD X,Y \ Y=3/4 cycle
18161 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18163 \ ******************************\
18164 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18165 \ ******************************\
18166 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18167 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18168 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18169 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18170 SUB #1,W \ decrement count loop
18171 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18172 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18173 0<> WHILE \ ----> out of loop ----+
18174 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18176 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18177 CMP Y,X \ 1 | cycle time out of bound ?
18178 U>= IF \ 2 ^ | yes:
18179 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18180 GOTO BW1 \ | | quit on truncated RC5 message
18182 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18184 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18185 \ ******************************\ |
18186 \ RC5_SampleEndOf: \ <---------------------+
18187 \ ******************************\
18188 BIC #$30,&RC5_TIM_CTL \ stop timer
18189 \ ******************************\
18190 \ RC5_ComputeNewRC5word \
18191 \ ******************************\
18192 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
18193 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
18194 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
18195 \ ******************************\
18196 \ RC5_ComputeC6bit \
18197 \ ******************************\
18198 BIT #BIT14,T \ test /C6 bit in T
18199 0= IF BIS #BIT6,X \ set C6 bit in X
18200 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
18201 \ ******************************\
18202 \ RC5_CommandByteIsDone \ -- BASE RC5_code
18203 \ ******************************\
18204 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18205 \ ******************************\
18206 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
18207 XOR @RSP,T \ (new XOR old) Toggle bits
18208 BIT #UF10,T \ repeated RC5_command ?
18209 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
18210 XOR #UF10,0(RSP) \ 5 toggle bit memory
18211 \ ******************************\
18212 \ Display IR_RC5 code \
18213 \ ******************************\
18214 SUB #8,PSP \ TOS -- x x x x TOS
18215 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
18216 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
18217 MOV #$10,&BASEADR \ set hexadecimal base
18218 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
18219 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
18220 LO2HI \ switch from assembler to FORTH
18221 LCD_CLEAR \ set LCD cursor at home
18222 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
18223 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
18224 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
18225 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
18226 HI2LO \ -- switch from FORTH to assembler
18227 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
18228 MOV @PSP+,TOS \ -- TOS
18232 \ ------------------------------\
18234 \ ------------------------------\
18236 \ ... \ insert here your background task
18239 CALL &RXON \ comment this line to disable TERMINAL
18241 \ ******************************\
18242 \ here start all interrupts \
18243 \ ******************************\
18244 \ here return all interrupts \
18245 \ ******************************\
18249 \ ------------------------------\
18250 CODE STOP \ stops multitasking, must to be used before downloading app
18251 \ ------------------------------\
18252 \ restore default action of primary DEFERred word SLEEP (assembly version)
18253 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
18254 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
18255 MOV X,-2(X) \ restore the default background
18256 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
18257 ['] WARM >BODY IS WARM \ restore the default WARM
18259 ." RC5toLCD is removed. type START to restart"
18260 COLD \ performs reset to reset all interrupt vectors.
18263 \ ------------------------------\
18264 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
18265 \ ------------------------------\
18266 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
18267 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18268 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18269 \ -- \ID input divider \ 10 = /4
18270 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
18271 \ - \TBCLR TimerB Clear
18274 \ -------------------------------\
18275 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18276 \ -- \CM Capture Mode
18281 \ --- \OUTMOD \ 011 = set/reset
18287 \ -------------------------------\
18289 \ -------------------------------\
18291 \ ------------------------------\
18292 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
18293 \ ------------------------------\
18294 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
18295 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
18296 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
18297 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
18299 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
18300 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
18302 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
18303 \ ------------------------------\
18304 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
18305 \ ------------------------------\
18306 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
18307 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
18308 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18309 \ ------------------------------\
18310 BIS.B #LCDVo,&LCDVo_DIR \
18311 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
18312 \ ------------------------------\
18313 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18314 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18315 \ ------------------------------\
18316 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18317 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18318 \ ******************************\
18320 \ ******************************\
18321 BIS.B #RC5,&IR_IE \ enable RC5_Int
18322 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18323 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18324 \ ******************************\
18325 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
18326 \ ******************************\
18327 \ %01 0001 0100 \ TAxCTL
18328 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
18329 \ -- \ ID divided by 1
18330 \ -- \ MC MODE = up to TAxCCRn
18331 \ - \ TACLR clear timer count
18334 \ ------------------------------\
18335 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
18336 \ ------------------------------\
18338 \ --- \ TAIDEX pre divisor
18339 \ ------------------------------\
18340 \ %0000 0000 0000 0101 \ TAxCCR0
18341 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
18342 \ ------------------------------\
18343 \ %0000 0000 0001 0000 \ TAxCCTL0
18344 \ - \ CAP capture/compare mode = compare
18347 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
18348 \ ------------------------------\
18349 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
18350 \ ------------------------------\
18351 \ define LPM mode for ACCEPT \
18352 \ ------------------------------\
18353 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18354 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18355 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18356 \ ------------------------------\
18358 \ ------------------------------\
18359 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
18360 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
18361 \ ------------------------------\
18362 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
18363 \ ------------------------------\
18364 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
18365 \ CMP #2,Y \ Power_ON event
18366 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
18368 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
18370 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
18372 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
18374 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
18375 \ ------------------------------\
18377 \ ------------------------------\
18379 \ ------------------------------\
18380 #1000 20_US \ 1- wait 20 ms
18381 %011 TOP_LCD \ 2- send DB5=DB4=1
18382 #205 20_US \ 3- wait 4,1 ms
18383 %011 TOP_LCD \ 4- send again DB5=DB4=1
18384 #5 20_US \ 5- wait 0,1 ms
18385 %011 TOP_LCD \ 6- send again again DB5=DB4=1
18386 #2 20_US \ wait 40 us = LCD cycle
18387 %010 TOP_LCD \ 7- send DB5=1 DB4=0
18388 #2 20_US \ wait 40 us = LCD cycle
18389 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18390 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18391 LCD_CLEAR \ 10- "LCD_Clear"
18392 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18393 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18394 LCD_CLEAR \ 10- "LCD_Clear"
18395 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18396 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18397 CR ." I love you" \ display message on LCD
18398 ['] CR >BODY IS CR \ CR executes its default value
18399 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
18400 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
18401 ABORT \ ...and end APP_INIT with ABORT, no return.
18404 \ ------------------------------\
18405 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
18406 \ ------------------------------\
18407 MOV #SLEEP,X \ replace default background process
18408 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
18409 MOV #WARM,X \ replace default WARM
18410 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
18411 MOV X,PC \ then execute it
18414 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
18418 CODE 20_US \ n -- n * 20 us
18419 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18421 BIT #1,&LCD_TIM_CTL \ 3
18422 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18423 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18425 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18430 CODE TOP_LCD \ LCD Sample
18431 \ \ if write : %xxxxWWWW --
18432 \ \ if read : -- %0000RRRR
18433 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18434 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18435 0= IF \ write LCD bits pattern
18436 AND.B #LCD_DB,TOS \
18437 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18438 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18441 THEN \ read LCD bits pattern
18444 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18445 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18446 AND.B #LCD_DB,TOS \
18450 CODE LCD_WRC \ char -- Write Char
18451 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18453 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18454 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18455 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18456 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18457 COLON \ high level word starts here
18458 TOP_LCD 2 20_US \ write high nibble first
18462 CODE LCD_WRF \ func -- Write Fonction
18463 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18467 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18468 : LCD_HOME $02 LCD_WRF 100 20_us ;
18470 \ [UNDEFINED] OR [IF]
18472 \ \ https://forth-standard.org/standard/core/OR
18473 \ \ C OR x1 x2 -- x3 logical OR
18481 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18482 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18483 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18484 \ : LCD_FN_SET $20 OR LCD_WrF ;
18485 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18486 \ : LCD_GOTO $80 OR LCD_WrF ;
18489 \ CODE LCD_RDS \ -- status Read Status
18490 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18491 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18492 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18493 \ COLON \ starts a FORTH word
18494 \ TOP_LCD 2 20_us \ -- %0000HHHH
18495 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18496 \ HI2LO \ switch from FORTH to assembler
18497 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18498 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18499 \ MOV @RSP+,IP \ restore IP saved by COLON
18503 \ CODE LCD_RDC \ -- char Read Char
18504 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18509 \ ******************************\
18510 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18511 \ ******************************\
18512 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18513 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18514 BIT.B #SW2,&SW2_IN \ test switch S2
18515 0= IF \ case of switch S2 pressed
18516 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18518 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18521 BIT.B #SW1,&SW1_IN \ test switch S1 input
18522 0= IF \ case of Switch S1 pressed
18523 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18525 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18529 BW1 \ from quit on truncated RC5 message, repeated RC5 command
18533 \ ******************************\
18534 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18535 \ ******************************\
18536 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18537 \ ******************************\
18538 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18539 \ \ SMclock = 8|16|24 MHz
18540 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18541 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18542 \ \ SR(9)=new Toggle bit memory (ADD on)
18543 \ ******************************\
18544 \ RC5_FirstStartBitHalfCycle: \
18545 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18546 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18547 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18548 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18550 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18551 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18553 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18554 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18556 MOV #1778,X \ RC5_Period * 1us
18557 MOV #14,W \ count of loop
18559 \ ******************************\
18560 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18561 \ ******************************\ |
18562 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18563 \ RC5_Compute_3/4_Period: \ |
18564 RRUM #1,X \ X=1/2 cycle |
18567 ADD X,Y \ Y=3/4 cycle
18568 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18570 \ ******************************\
18571 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18572 \ ******************************\
18573 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18574 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18575 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18576 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18577 SUB #1,W \ decrement count loop
18578 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18579 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18580 0<> WHILE \ ----> out of loop ----+
18581 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18583 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18584 CMP Y,X \ 1 | cycle time out of bound ?
18585 U>= IF \ 2 ^ | yes:
18586 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18587 GOTO BW1 \ | | quit on truncated RC5 message
18589 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18591 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18592 \ ******************************\ |
18593 \ RC5_SampleEndOf: \ <---------------------+
18594 \ ******************************\
18595 BIC #$30,&RC5_TIM_CTL \ stop timer
18596 \ ******************************\
18597 \ RC5_ComputeNewRC5word \
18598 \ ******************************\
18599 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
18600 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
18601 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
18602 \ ******************************\
18603 \ RC5_ComputeC6bit \
18604 \ ******************************\
18605 BIT #BIT14,T \ test /C6 bit in T
18606 0= IF BIS #BIT6,X \ set C6 bit in X
18607 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
18608 \ ******************************\
18609 \ RC5_CommandByteIsDone \ -- BASE RC5_code
18610 \ ******************************\
18611 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18612 \ ******************************\
18613 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
18614 XOR @RSP,T \ (new XOR old) Toggle bits
18615 BIT #UF10,T \ repeated RC5_command ?
18616 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
18617 XOR #UF10,0(RSP) \ 5 toggle bit memory
18618 \ ******************************\
18619 \ Display IR_RC5 code \
18620 \ ******************************\
18621 SUB #8,PSP \ TOS -- x x x x TOS
18622 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
18623 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
18624 MOV #$10,&BASEADR \ set hexadecimal base
18625 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
18626 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
18627 LO2HI \ switch from assembler to FORTH
18628 LCD_CLEAR \ set LCD cursor at home
18629 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
18630 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
18631 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
18632 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
18633 HI2LO \ -- switch from FORTH to assembler
18634 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
18635 MOV @PSP+,TOS \ -- TOS
18639 \ ------------------------------\
18641 \ ------------------------------\
18643 \ ... \ insert here your background task
18646 CALL &RXON \ comment this line to disable TERMINAL
18648 \ ******************************\
18649 \ here start all interrupts \
18650 \ ******************************\
18651 \ here return all interrupts \
18652 \ ******************************\
18656 \ ------------------------------\
18657 CODE STOP \ stops multitasking, must to be used before downloading app
18658 \ ------------------------------\
18659 \ restore default action of primary DEFERred word SLEEP (assembly version)
18660 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
18661 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
18662 MOV X,-2(X) \ restore the default background
18663 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
18664 ['] WARM >BODY IS WARM \ restore the default WARM
18666 ." RC5toLCD is removed. type START to restart"
18667 COLD \ performs reset to reset all interrupt vectors.
18670 \ ------------------------------\
18671 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
18672 \ ------------------------------\
18673 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
18674 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18675 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18676 \ -- \ID input divider \ 10 = /4
18677 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
18678 \ - \TBCLR TimerB Clear
18681 \ -------------------------------\
18682 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18683 \ -- \CM Capture Mode
18688 \ --- \OUTMOD \ 011 = set/reset
18694 \ -------------------------------\
18696 \ -------------------------------\
18698 \ ------------------------------\
18699 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
18700 \ ------------------------------\
18701 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
18702 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
18703 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
18704 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
18706 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
18707 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
18709 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
18710 \ ------------------------------\
18711 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
18712 \ ------------------------------\
18713 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
18714 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
18715 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18716 \ ------------------------------\
18717 BIS.B #LCDVo,&LCDVo_DIR \
18718 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
18719 \ ------------------------------\
18720 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18721 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18722 \ ------------------------------\
18723 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18724 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18725 \ ******************************\
18727 \ ******************************\
18728 BIS.B #RC5,&IR_IE \ enable RC5_Int
18729 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18730 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18731 \ ******************************\
18732 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
18733 \ ******************************\
18734 \ %01 0001 0100 \ TAxCTL
18735 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
18736 \ -- \ ID divided by 1
18737 \ -- \ MC MODE = up to TAxCCRn
18738 \ - \ TACLR clear timer count
18741 \ ------------------------------\
18742 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
18743 \ ------------------------------\
18745 \ --- \ TAIDEX pre divisor
18746 \ ------------------------------\
18747 \ %0000 0000 0000 0101 \ TAxCCR0
18748 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
18749 \ ------------------------------\
18750 \ %0000 0000 0001 0000 \ TAxCCTL0
18751 \ - \ CAP capture/compare mode = compare
18754 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
18755 \ ------------------------------\
18756 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
18757 \ ------------------------------\
18758 \ define LPM mode for ACCEPT \
18759 \ ------------------------------\
18760 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18761 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18762 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18763 \ ------------------------------\
18765 \ ------------------------------\
18766 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
18767 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
18768 \ ------------------------------\
18769 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
18770 \ ------------------------------\
18771 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
18772 \ CMP #2,Y \ Power_ON event
18773 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
18775 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
18777 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
18779 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
18781 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
18782 \ ------------------------------\
18784 \ ------------------------------\
18786 \ ------------------------------\
18787 #1000 20_US \ 1- wait 20 ms
18788 %011 TOP_LCD \ 2- send DB5=DB4=1
18789 #205 20_US \ 3- wait 4,1 ms
18790 %011 TOP_LCD \ 4- send again DB5=DB4=1
18791 #5 20_US \ 5- wait 0,1 ms
18792 %011 TOP_LCD \ 6- send again again DB5=DB4=1
18793 #2 20_US \ wait 40 us = LCD cycle
18794 %010 TOP_LCD \ 7- send DB5=1 DB4=0
18795 #2 20_US \ wait 40 us = LCD cycle
18796 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18797 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18798 LCD_CLEAR \ 10- "LCD_Clear"
18799 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18800 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18801 LCD_CLEAR \ 10- "LCD_Clear"
18802 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18803 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18804 CR ." I love you" \ display message on LCD
18805 ['] CR >BODY IS CR \ CR executes its default value
18806 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
18807 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
18808 ABORT \ ...and end APP_INIT with ABORT, no return.
18811 \ ------------------------------\
18812 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
18813 \ ------------------------------\
18814 MOV #SLEEP,X \ replace default background process
18815 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
18816 MOV #WARM,X \ replace default WARM
18817 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
18818 MOV X,PC \ then execute it
18821 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
18825 CODE 20_US \ n -- n * 20 us
18826 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18828 BIT #1,&LCD_TIM_CTL \ 3
18829 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18830 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18832 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18837 CODE TOP_LCD \ LCD Sample
18838 \ \ if write : %xxxxWWWW --
18839 \ \ if read : -- %0000RRRR
18840 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18841 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18842 0= IF \ write LCD bits pattern
18843 AND.B #LCD_DB,TOS \
18844 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18845 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18848 THEN \ read LCD bits pattern
18851 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18852 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18853 AND.B #LCD_DB,TOS \
18857 CODE LCD_WRC \ char -- Write Char
18858 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18860 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18861 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18862 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18863 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18864 COLON \ high level word starts here
18865 TOP_LCD 2 20_US \ write high nibble first
18869 CODE LCD_WRF \ func -- Write Fonction
18870 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18874 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18875 : LCD_HOME $02 LCD_WRF 100 20_us ;
18877 \ [UNDEFINED] OR [IF]
18879 \ \ https://forth-standard.org/standard/core/OR
18880 \ \ C OR x1 x2 -- x3 logical OR
18888 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18889 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18890 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18891 \ : LCD_FN_SET $20 OR LCD_WrF ;
18892 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18893 \ : LCD_GOTO $80 OR LCD_WrF ;
18896 \ CODE LCD_RDS \ -- status Read Status
18897 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18898 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18899 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18900 \ COLON \ starts a FORTH word
18901 \ TOP_LCD 2 20_us \ -- %0000HHHH
18902 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18903 \ HI2LO \ switch from FORTH to assembler
18904 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18905 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18906 \ MOV @RSP+,IP \ restore IP saved by COLON
18910 \ CODE LCD_RDC \ -- char Read Char
18911 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18916 \ ******************************\
18917 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18918 \ ******************************\
18919 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18920 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18921 BIT.B #SW2,&SW2_IN \ test switch S2
18922 0= IF \ case of switch S2 pressed
18923 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18925 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18928 BIT.B #SW1,&SW1_IN \ test switch S1 input
18929 0= IF \ case of Switch S1 pressed
18930 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18932 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18936 BW1 \ from quit on truncated RC5 message, repeated RC5 command
18940 \ ******************************\
18941 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18942 \ ******************************\
18943 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18944 \ ******************************\
18945 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18946 \ \ SMclock = 8|16|24 MHz
18947 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18948 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18949 \ \ SR(9)=new Toggle bit memory (ADD on)
18950 \ ******************************\
18951 \ RC5_FirstStartBitHalfCycle: \
18952 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18953 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18954 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18955 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18957 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18958 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18960 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18961 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18963 MOV #1778,X \ RC5_Period * 1us
18964 MOV #14,W \ count of loop
18966 \ ******************************\
18967 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18968 \ ******************************\ |
18969 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18970 \ RC5_Compute_3/4_Period: \ |
18971 RRUM #1,X \ X=1/2 cycle |
18974 ADD X,Y \ Y=3/4 cycle
18975 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18977 \ ******************************\
18978 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18979 \ ******************************\
18980 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18981 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18982 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18983 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18984 SUB #1,W \ decrement count loop
18985 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18986 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18987 0<> WHILE \ ----> out of loop ----+
18988 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18990 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18991 CMP Y,X \ 1 | cycle time out of bound ?
18992 U>= IF \ 2 ^ | yes:
18993 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18994 GOTO BW1 \ | | quit on truncated RC5 message
18996 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18998 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18999 \ ******************************\ |
19000 \ RC5_SampleEndOf: \ <---------------------+
19001 \ ******************************\
19002 BIC #$30,&RC5_TIM_CTL \ stop timer
19003 \ ******************************\
19004 \ RC5_ComputeNewRC5word \
19005 \ ******************************\
19006 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
19007 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
19008 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
19009 \ ******************************\
19010 \ RC5_ComputeC6bit \
19011 \ ******************************\
19012 BIT #BIT14,T \ test /C6 bit in T
19013 0= IF BIS #BIT6,X \ set C6 bit in X
19014 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
19015 \ ******************************\
19016 \ RC5_CommandByteIsDone \ -- BASE RC5_code
19017 \ ******************************\
19018 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19019 \ ******************************\
19020 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
19021 XOR @RSP,T \ (new XOR old) Toggle bits
19022 BIT #UF10,T \ repeated RC5_command ?
19023 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
19024 XOR #UF10,0(RSP) \ 5 toggle bit memory
19025 \ ******************************\
19026 \ Display IR_RC5 code \
19027 \ ******************************\
19028 SUB #8,PSP \ TOS -- x x x x TOS
19029 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19030 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19031 MOV #$10,&BASEADR \ set hexadecimal base
19032 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19033 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19034 LO2HI \ switch from assembler to FORTH
19035 LCD_CLEAR \ set LCD cursor at home
19036 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19037 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19038 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19039 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19040 HI2LO \ -- switch from FORTH to assembler
19041 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19042 MOV @PSP+,TOS \ -- TOS
19046 \ ------------------------------\
19048 \ ------------------------------\
19050 \ ... \ insert here your background task
19053 CALL &RXON \ comment this line to disable TERMINAL
19055 \ ******************************\
19056 \ here start all interrupts \
19057 \ ******************************\
19058 \ here return all interrupts \
19059 \ ******************************\
19063 \ ------------------------------\
19064 CODE STOP \ stops multitasking, must to be used before downloading app
19065 \ ------------------------------\
19066 \ restore default action of primary DEFERred word SLEEP (assembly version)
19067 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
19068 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19069 MOV X,-2(X) \ restore the default background
19070 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19071 ['] WARM >BODY IS WARM \ restore the default WARM
19073 ." RC5toLCD is removed. type START to restart"
19074 COLD \ performs reset to reset all interrupt vectors.
19077 \ ------------------------------\
19078 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
19079 \ ------------------------------\
19080 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19081 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19082 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19083 \ -- \ID input divider \ 10 = /4
19084 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19085 \ - \TBCLR TimerB Clear
19088 \ -------------------------------\
19089 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19090 \ -- \CM Capture Mode
19095 \ --- \OUTMOD \ 011 = set/reset
19101 \ -------------------------------\
19103 \ -------------------------------\
19105 \ ------------------------------\
19106 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19107 \ ------------------------------\
19108 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19109 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19110 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19111 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19113 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19114 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19116 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19117 \ ------------------------------\
19118 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19119 \ ------------------------------\
19120 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19121 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19122 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19123 \ ------------------------------\
19124 BIS.B #LCDVo,&LCDVo_DIR \
19125 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19126 \ ------------------------------\
19127 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19128 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19129 \ ------------------------------\
19130 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19131 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19132 \ ******************************\
19134 \ ******************************\
19135 BIS.B #RC5,&IR_IE \ enable RC5_Int
19136 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19137 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19138 \ ******************************\
19139 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19140 \ ******************************\
19141 \ %01 0001 0100 \ TAxCTL
19142 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19143 \ -- \ ID divided by 1
19144 \ -- \ MC MODE = up to TAxCCRn
19145 \ - \ TACLR clear timer count
19148 \ ------------------------------\
19149 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19150 \ ------------------------------\
19152 \ --- \ TAIDEX pre divisor
19153 \ ------------------------------\
19154 \ %0000 0000 0000 0101 \ TAxCCR0
19155 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19156 \ ------------------------------\
19157 \ %0000 0000 0001 0000 \ TAxCCTL0
19158 \ - \ CAP capture/compare mode = compare
19161 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19162 \ ------------------------------\
19163 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19164 \ ------------------------------\
19165 \ define LPM mode for ACCEPT \
19166 \ ------------------------------\
19167 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19168 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19169 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19170 \ ------------------------------\
19172 \ ------------------------------\
19173 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
19174 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19175 \ ------------------------------\
19176 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19177 \ ------------------------------\
19178 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
19179 \ CMP #2,Y \ Power_ON event
19180 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19182 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
19184 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
19186 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
19188 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
19189 \ ------------------------------\
19191 \ ------------------------------\
19193 \ ------------------------------\
19194 #1000 20_US \ 1- wait 20 ms
19195 %011 TOP_LCD \ 2- send DB5=DB4=1
19196 #205 20_US \ 3- wait 4,1 ms
19197 %011 TOP_LCD \ 4- send again DB5=DB4=1
19198 #5 20_US \ 5- wait 0,1 ms
19199 %011 TOP_LCD \ 6- send again again DB5=DB4=1
19200 #2 20_US \ wait 40 us = LCD cycle
19201 %010 TOP_LCD \ 7- send DB5=1 DB4=0
19202 #2 20_US \ wait 40 us = LCD cycle
19203 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19204 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19205 LCD_CLEAR \ 10- "LCD_Clear"
19206 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19207 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19208 LCD_CLEAR \ 10- "LCD_Clear"
19209 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19210 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19211 CR ." I love you" \ display message on LCD
19212 ['] CR >BODY IS CR \ CR executes its default value
19213 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
19214 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19215 ABORT \ ...and end APP_INIT with ABORT, no return.
19218 \ ------------------------------\
19219 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
19220 \ ------------------------------\
19221 MOV #SLEEP,X \ replace default background process
19222 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
19223 MOV #WARM,X \ replace default WARM
19224 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
19225 MOV X,PC \ then execute it
19228 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
19232 CODE 20_US \ n -- n * 20 us
19233 BEGIN \ here we presume that LCD_TIM_IFG = 1...
19235 BIT #1,&LCD_TIM_CTL \ 3
19236 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
19237 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
19239 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
19244 CODE TOP_LCD \ LCD Sample
19245 \ \ if write : %xxxxWWWW --
19246 \ \ if read : -- %0000RRRR
19247 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19248 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19249 0= IF \ write LCD bits pattern
19250 AND.B #LCD_DB,TOS \
19251 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19252 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19255 THEN \ read LCD bits pattern
19258 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19259 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19260 AND.B #LCD_DB,TOS \
19264 CODE LCD_WRC \ char -- Write Char
19265 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19267 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
19268 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
19269 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19270 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19271 COLON \ high level word starts here
19272 TOP_LCD 2 20_US \ write high nibble first
19276 CODE LCD_WRF \ func -- Write Fonction
19277 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19281 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
19282 : LCD_HOME $02 LCD_WRF 100 20_us ;
19284 \ [UNDEFINED] OR [IF]
19286 \ \ https://forth-standard.org/standard/core/OR
19287 \ \ C OR x1 x2 -- x3 logical OR
19295 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
19296 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
19297 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
19298 \ : LCD_FN_SET $20 OR LCD_WrF ;
19299 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
19300 \ : LCD_GOTO $80 OR LCD_WrF ;
19303 \ CODE LCD_RDS \ -- status Read Status
19304 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19305 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19306 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19307 \ COLON \ starts a FORTH word
19308 \ TOP_LCD 2 20_us \ -- %0000HHHH
19309 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
19310 \ HI2LO \ switch from FORTH to assembler
19311 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
19312 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
19313 \ MOV @RSP+,IP \ restore IP saved by COLON
19317 \ CODE LCD_RDC \ -- char Read Char
19318 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19323 \ ******************************\
19324 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19325 \ ******************************\
19326 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
19327 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
19328 BIT.B #SW2,&SW2_IN \ test switch S2
19329 0= IF \ case of switch S2 pressed
19330 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
19332 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
19335 BIT.B #SW1,&SW1_IN \ test switch S1 input
19336 0= IF \ case of Switch S1 pressed
19337 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
19339 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
19343 BW1 \ from quit on truncated RC5 message, repeated RC5 command
19347 \ ******************************\
19348 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19349 \ ******************************\
19350 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19351 \ ******************************\
19352 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19353 \ \ SMclock = 8|16|24 MHz
19354 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
19355 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
19356 \ \ SR(9)=new Toggle bit memory (ADD on)
19357 \ ******************************\
19358 \ RC5_FirstStartBitHalfCycle: \
19359 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
19360 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
19361 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
19362 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
19364 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
19365 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
19367 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
19368 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
19370 MOV #1778,X \ RC5_Period * 1us
19371 MOV #14,W \ count of loop
19373 \ ******************************\
19374 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
19375 \ ******************************\ |
19376 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
19377 \ RC5_Compute_3/4_Period: \ |
19378 RRUM #1,X \ X=1/2 cycle |
19381 ADD X,Y \ Y=3/4 cycle
19382 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
19384 \ ******************************\
19385 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
19386 \ ******************************\
19387 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19388 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
19389 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19390 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19391 SUB #1,W \ decrement count loop
19392 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
19393 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19394 0<> WHILE \ ----> out of loop ----+
19395 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
19397 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
19398 CMP Y,X \ 1 | cycle time out of bound ?
19399 U>= IF \ 2 ^ | yes:
19400 BIC #$30,&RC5_TIM_CTL \ | | stop timer
19401 GOTO BW1 \ | | quit on truncated RC5 message
19403 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
19405 REPEAT \ ----> loop back --+ | with X = new RC5_period value
19406 \ ******************************\ |
19407 \ RC5_SampleEndOf: \ <---------------------+
19408 \ ******************************\
19409 BIC #$30,&RC5_TIM_CTL \ stop timer
19410 \ ******************************\
19411 \ RC5_ComputeNewRC5word \
19412 \ ******************************\
19413 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
19414 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
19415 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
19416 \ ******************************\
19417 \ RC5_ComputeC6bit \
19418 \ ******************************\
19419 BIT #BIT14,T \ test /C6 bit in T
19420 0= IF BIS #BIT6,X \ set C6 bit in X
19421 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
19422 \ ******************************\
19423 \ RC5_CommandByteIsDone \ -- BASE RC5_code
19424 \ ******************************\
19425 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19426 \ ******************************\
19427 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
19428 XOR @RSP,T \ (new XOR old) Toggle bits
19429 BIT #UF10,T \ repeated RC5_command ?
19430 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
19431 XOR #UF10,0(RSP) \ 5 toggle bit memory
19432 \ ******************************\
19433 \ Display IR_RC5 code \
19434 \ ******************************\
19435 SUB #8,PSP \ TOS -- x x x x TOS
19436 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19437 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19438 MOV #$10,&BASEADR \ set hexadecimal base
19439 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19440 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19441 LO2HI \ switch from assembler to FORTH
19442 LCD_CLEAR \ set LCD cursor at home
19443 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19444 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19445 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19446 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19447 HI2LO \ -- switch from FORTH to assembler
19448 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19449 MOV @PSP+,TOS \ -- TOS
19453 \ ------------------------------\
19455 \ ------------------------------\
19457 \ ... \ insert here your background task
19460 CALL &RXON \ comment this line to disable TERMINAL
19462 \ ******************************\
19463 \ here start all interrupts \
19464 \ ******************************\
19465 \ here return all interrupts \
19466 \ ******************************\
19470 \ ------------------------------\
19471 CODE STOP \ stops multitasking, must to be used before downloading app
19472 \ ------------------------------\
19473 \ restore default action of primary DEFERred word SLEEP (assembly version)
19474 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
19475 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19476 MOV X,-2(X) \ restore the default background
19477 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19478 ['] WARM >BODY IS WARM \ restore the default WARM
19480 ." RC5toLCD is removed. type START to restart"
19481 COLD \ performs reset to reset all interrupt vectors.
19484 \ ------------------------------\
19485 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
19486 \ ------------------------------\
19487 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19488 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19489 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19490 \ -- \ID input divider \ 10 = /4
19491 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19492 \ - \TBCLR TimerB Clear
19495 \ -------------------------------\
19496 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19497 \ -- \CM Capture Mode
19502 \ --- \OUTMOD \ 011 = set/reset
19508 \ -------------------------------\
19510 \ -------------------------------\
19512 \ ------------------------------\
19513 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19514 \ ------------------------------\
19515 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19516 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19517 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19518 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19520 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19521 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19523 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19524 \ ------------------------------\
19525 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19526 \ ------------------------------\
19527 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19528 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19529 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19530 \ ------------------------------\
19531 BIS.B #LCDVo,&LCDVo_DIR \
19532 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19533 \ ------------------------------\
19534 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19535 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19536 \ ------------------------------\
19537 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19538 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19539 \ ******************************\
19541 \ ******************************\
19542 BIS.B #RC5,&IR_IE \ enable RC5_Int
19543 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19544 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19545 \ ******************************\
19546 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19547 \ ******************************\
19548 \ %01 0001 0100 \ TAxCTL
19549 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19550 \ -- \ ID divided by 1
19551 \ -- \ MC MODE = up to TAxCCRn
19552 \ - \ TACLR clear timer count
19555 \ ------------------------------\
19556 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19557 \ ------------------------------\
19559 \ --- \ TAIDEX pre divisor
19560 \ ------------------------------\
19561 \ %0000 0000 0000 0101 \ TAxCCR0
19562 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19563 \ ------------------------------\
19564 \ %0000 0000 0001 0000 \ TAxCCTL0
19565 \ - \ CAP capture/compare mode = compare
19568 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19569 \ ------------------------------\
19570 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19571 \ ------------------------------\
19572 \ define LPM mode for ACCEPT \
19573 \ ------------------------------\
19574 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19575 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19576 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19577 \ ------------------------------\
19579 \ ------------------------------\
19580 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
19581 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19582 \ ------------------------------\
19583 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19584 \ ------------------------------\
19585 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
19586 \ CMP #2,Y \ Power_ON event
19587 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19589 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
19591 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
19593 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
19595 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
19596 \ ------------------------------\
19598 \ ------------------------------\
19600 \ ------------------------------\
19601 #1000 20_US \ 1- wait 20 ms
19602 %011 TOP_LCD \ 2- send DB5=DB4=1
19603 #205 20_US \ 3- wait 4,1 ms
19604 %011 TOP_LCD \ 4- send again DB5=DB4=1
19605 #5 20_US \ 5- wait 0,1 ms
19606 %011 TOP_LCD \ 6- send again again DB5=DB4=1
19607 #2 20_US \ wait 40 us = LCD cycle
19608 %010 TOP_LCD \ 7- send DB5=1 DB4=0
19609 #2 20_US \ wait 40 us = LCD cycle
19610 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19611 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19612 LCD_CLEAR \ 10- "LCD_Clear"
19613 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19614 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19615 LCD_CLEAR \ 10- "LCD_Clear"
19616 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19617 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19618 CR ." I love you" \ display message on LCD
19619 ['] CR >BODY IS CR \ CR executes its default value
19620 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
19621 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19622 ABORT \ ...and end APP_INIT with ABORT, no return.
19625 \ ------------------------------\
19626 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
19627 \ ------------------------------\
19628 MOV #SLEEP,X \ replace default background process
19629 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
19630 MOV #WARM,X \ replace default WARM
19631 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
19632 MOV X,PC \ then execute it
19635 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
19639 CODE 20_US \ n -- n * 20 us
19640 BEGIN \ here we presume that LCD_TIM_IFG = 1...
19642 BIT #1,&LCD_TIM_CTL \ 3
19643 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
19644 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
19646 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
19651 CODE TOP_LCD \ LCD Sample
19652 \ \ if write : %xxxxWWWW --
19653 \ \ if read : -- %0000RRRR
19654 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19655 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19656 0= IF \ write LCD bits pattern
19657 AND.B #LCD_DB,TOS \
19658 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19659 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19662 THEN \ read LCD bits pattern
19665 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19666 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19667 AND.B #LCD_DB,TOS \
19671 CODE LCD_WRC \ char -- Write Char
19672 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19674 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
19675 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
19676 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19677 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19678 COLON \ high level word starts here
19679 TOP_LCD 2 20_US \ write high nibble first
19683 CODE LCD_WRF \ func -- Write Fonction
19684 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19688 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
19689 : LCD_HOME $02 LCD_WRF 100 20_us ;
19691 \ [UNDEFINED] OR [IF]
19693 \ \ https://forth-standard.org/standard/core/OR
19694 \ \ C OR x1 x2 -- x3 logical OR
19702 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
19703 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
19704 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
19705 \ : LCD_FN_SET $20 OR LCD_WrF ;
19706 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
19707 \ : LCD_GOTO $80 OR LCD_WrF ;
19710 \ CODE LCD_RDS \ -- status Read Status
19711 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19712 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19713 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19714 \ COLON \ starts a FORTH word
19715 \ TOP_LCD 2 20_us \ -- %0000HHHH
19716 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
19717 \ HI2LO \ switch from FORTH to assembler
19718 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
19719 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
19720 \ MOV @RSP+,IP \ restore IP saved by COLON
19724 \ CODE LCD_RDC \ -- char Read Char
19725 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19730 \ ******************************\
19731 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19732 \ ******************************\
19733 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
19734 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
19735 BIT.B #SW2,&SW2_IN \ test switch S2
19736 0= IF \ case of switch S2 pressed
19737 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
19739 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
19742 BIT.B #SW1,&SW1_IN \ test switch S1 input
19743 0= IF \ case of Switch S1 pressed
19744 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
19746 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
19750 BW1 \ from quit on truncated RC5 message, repeated RC5 command
19754 \ ******************************\
19755 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19756 \ ******************************\
19757 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19758 \ ******************************\
19759 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19760 \ \ SMclock = 8|16|24 MHz
19761 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
19762 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
19763 \ \ SR(9)=new Toggle bit memory (ADD on)
19764 \ ******************************\
19765 \ RC5_FirstStartBitHalfCycle: \
19766 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
19767 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
19768 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
19769 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
19771 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
19772 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
19774 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
19775 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
19777 MOV #1778,X \ RC5_Period * 1us
19778 MOV #14,W \ count of loop
19780 \ ******************************\
19781 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
19782 \ ******************************\ |
19783 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
19784 \ RC5_Compute_3/4_Period: \ |
19785 RRUM #1,X \ X=1/2 cycle |
19788 ADD X,Y \ Y=3/4 cycle
19789 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
19791 \ ******************************\
19792 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
19793 \ ******************************\
19794 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19795 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
19796 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19797 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19798 SUB #1,W \ decrement count loop
19799 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
19800 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19801 0<> WHILE \ ----> out of loop ----+
19802 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
19804 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
19805 CMP Y,X \ 1 | cycle time out of bound ?
19806 U>= IF \ 2 ^ | yes:
19807 BIC #$30,&RC5_TIM_CTL \ | | stop timer
19808 GOTO BW1 \ | | quit on truncated RC5 message
19810 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
19812 REPEAT \ ----> loop back --+ | with X = new RC5_period value
19813 \ ******************************\ |
19814 \ RC5_SampleEndOf: \ <---------------------+
19815 \ ******************************\
19816 BIC #$30,&RC5_TIM_CTL \ stop timer
19817 \ ******************************\
19818 \ RC5_ComputeNewRC5word \
19819 \ ******************************\
19820 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
19821 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
19822 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
19823 \ ******************************\
19824 \ RC5_ComputeC6bit \
19825 \ ******************************\
19826 BIT #BIT14,T \ test /C6 bit in T
19827 0= IF BIS #BIT6,X \ set C6 bit in X
19828 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
19829 \ ******************************\
19830 \ RC5_CommandByteIsDone \ -- BASE RC5_code
19831 \ ******************************\
19832 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19833 \ ******************************\
19834 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
19835 XOR @RSP,T \ (new XOR old) Toggle bits
19836 BIT #UF10,T \ repeated RC5_command ?
19837 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
19838 XOR #UF10,0(RSP) \ 5 toggle bit memory
19839 \ ******************************\
19840 \ Display IR_RC5 code \
19841 \ ******************************\
19842 SUB #8,PSP \ TOS -- x x x x TOS
19843 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19844 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19845 MOV #$10,&BASEADR \ set hexadecimal base
19846 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19847 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19848 LO2HI \ switch from assembler to FORTH
19849 LCD_CLEAR \ set LCD cursor at home
19850 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19851 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19852 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19853 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19854 HI2LO \ -- switch from FORTH to assembler
19855 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19856 MOV @PSP+,TOS \ -- TOS
19860 \ ------------------------------\
19862 \ ------------------------------\
19864 \ ... \ insert here your background task
19867 CALL &RXON \ comment this line to disable TERMINAL
19869 \ ******************************\
19870 \ here start all interrupts \
19871 \ ******************************\
19872 \ here return all interrupts \
19873 \ ******************************\
19877 \ ------------------------------\
19878 CODE STOP \ stops multitasking, must to be used before downloading app
19879 \ ------------------------------\
19880 \ restore default action of primary DEFERred word SLEEP (assembly version)
19881 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
19882 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19883 MOV X,-2(X) \ restore the default background
19884 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19885 ['] WARM >BODY IS WARM \ restore the default WARM
19887 ." RC5toLCD is removed. type START to restart"
19888 COLD \ performs reset to reset all interrupt vectors.
19891 \ ------------------------------\
19892 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
19893 \ ------------------------------\
19894 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19895 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19896 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19897 \ -- \ID input divider \ 10 = /4
19898 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19899 \ - \TBCLR TimerB Clear
19902 \ -------------------------------\
19903 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19904 \ -- \CM Capture Mode
19909 \ --- \OUTMOD \ 011 = set/reset
19915 \ -------------------------------\
19917 \ -------------------------------\
19919 \ ------------------------------\
19920 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19921 \ ------------------------------\
19922 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19923 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19924 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19925 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19927 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19928 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19930 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19931 \ ------------------------------\
19932 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19933 \ ------------------------------\
19934 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19935 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19936 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19937 \ ------------------------------\
19938 BIS.B #LCDVo,&LCDVo_DIR \
19939 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19940 \ ------------------------------\
19941 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19942 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19943 \ ------------------------------\
19944 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19945 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19946 \ ******************************\
19948 \ ******************************\
19949 BIS.B #RC5,&IR_IE \ enable RC5_Int
19950 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19951 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19952 \ ******************************\
19953 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19954 \ ******************************\
19955 \ %01 0001 0100 \ TAxCTL
19956 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19957 \ -- \ ID divided by 1
19958 \ -- \ MC MODE = up to TAxCCRn
19959 \ - \ TACLR clear timer count
19962 \ ------------------------------\
19963 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19964 \ ------------------------------\
19966 \ --- \ TAIDEX pre divisor
19967 \ ------------------------------\
19968 \ %0000 0000 0000 0101 \ TAxCCR0
19969 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19970 \ ------------------------------\
19971 \ %0000 0000 0001 0000 \ TAxCCTL0
19972 \ - \ CAP capture/compare mode = compare
19975 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19976 \ ------------------------------\
19977 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19978 \ ------------------------------\
19979 \ define LPM mode for ACCEPT \
19980 \ ------------------------------\
19981 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19982 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19983 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19984 \ ------------------------------\
19986 \ ------------------------------\
19987 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
19988 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19989 \ ------------------------------\
19990 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19991 \ ------------------------------\
19992 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
19993 \ CMP #2,Y \ Power_ON event
19994 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19996 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
19998 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
20000 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
20002 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
20003 \ ------------------------------\
20005 \ ------------------------------\
20007 \ ------------------------------\
20008 #1000 20_US \ 1- wait 20 ms
20009 %011 TOP_LCD \ 2- send DB5=DB4=1
20010 #205 20_US \ 3- wait 4,1 ms
20011 %011 TOP_LCD \ 4- send again DB5=DB4=1
20012 #5 20_US \ 5- wait 0,1 ms
20013 %011 TOP_LCD \ 6- send again again DB5=DB4=1
20014 #2 20_US \ wait 40 us = LCD cycle
20015 %010 TOP_LCD \ 7- send DB5=1 DB4=0
20016 #2 20_US \ wait 40 us = LCD cycle
20017 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20018 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20019 LCD_CLEAR \ 10- "LCD_Clear"
20020 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20021 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20022 LCD_CLEAR \ 10- "LCD_Clear"
20023 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20024 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20025 CR ." I love you" \ display message on LCD
20026 ['] CR >BODY IS CR \ CR executes its default value
20027 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
20028 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20029 ABORT \ ...and end APP_INIT with ABORT, no return.
20032 \ ------------------------------\
20033 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
20034 \ ------------------------------\
20035 MOV #SLEEP,X \ replace default background process
20036 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
20037 MOV #WARM,X \ replace default WARM
20038 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
20039 MOV X,PC \ then execute it
20042 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
20046 CODE 20_US \ n -- n * 20 us
20047 BEGIN \ here we presume that LCD_TIM_IFG = 1...
20049 BIT #1,&LCD_TIM_CTL \ 3
20050 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
20051 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
20053 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
20058 CODE TOP_LCD \ LCD Sample
20059 \ \ if write : %xxxxWWWW --
20060 \ \ if read : -- %0000RRRR
20061 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20062 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20063 0= IF \ write LCD bits pattern
20064 AND.B #LCD_DB,TOS \
20065 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20066 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20069 THEN \ read LCD bits pattern
20072 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20073 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20074 AND.B #LCD_DB,TOS \
20078 CODE LCD_WRC \ char -- Write Char
20079 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20081 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20082 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20083 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20084 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20085 COLON \ high level word starts here
20086 TOP_LCD 2 20_US \ write high nibble first
20090 CODE LCD_WRF \ func -- Write Fonction
20091 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20095 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
20096 : LCD_HOME $02 LCD_WRF 100 20_us ;
20098 \ [UNDEFINED] OR [IF]
20100 \ \ https://forth-standard.org/standard/core/OR
20101 \ \ C OR x1 x2 -- x3 logical OR
20109 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
20110 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
20111 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
20112 \ : LCD_FN_SET $20 OR LCD_WrF ;
20113 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
20114 \ : LCD_GOTO $80 OR LCD_WrF ;
20117 \ CODE LCD_RDS \ -- status Read Status
20118 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20119 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20120 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20121 \ COLON \ starts a FORTH word
20122 \ TOP_LCD 2 20_us \ -- %0000HHHH
20123 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20124 \ HI2LO \ switch from FORTH to assembler
20125 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20126 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20127 \ MOV @RSP+,IP \ restore IP saved by COLON
20131 \ CODE LCD_RDC \ -- char Read Char
20132 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20137 \ ******************************\
20138 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20139 \ ******************************\
20140 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20141 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20142 BIT.B #SW2,&SW2_IN \ test switch S2
20143 0= IF \ case of switch S2 pressed
20144 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20146 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20149 BIT.B #SW1,&SW1_IN \ test switch S1 input
20150 0= IF \ case of Switch S1 pressed
20151 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20153 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20157 BW1 \ from quit on truncated RC5 message, repeated RC5 command
20161 \ ******************************\
20162 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20163 \ ******************************\
20164 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20165 \ ******************************\
20166 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20167 \ \ SMclock = 8|16|24 MHz
20168 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20169 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20170 \ \ SR(9)=new Toggle bit memory (ADD on)
20171 \ ******************************\
20172 \ RC5_FirstStartBitHalfCycle: \
20173 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20174 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20175 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20176 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20178 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20179 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20181 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20182 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20184 MOV #1778,X \ RC5_Period * 1us
20185 MOV #14,W \ count of loop
20187 \ ******************************\
20188 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
20189 \ ******************************\ |
20190 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20191 \ RC5_Compute_3/4_Period: \ |
20192 RRUM #1,X \ X=1/2 cycle |
20195 ADD X,Y \ Y=3/4 cycle
20196 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
20198 \ ******************************\
20199 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20200 \ ******************************\
20201 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20202 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
20203 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20204 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20205 SUB #1,W \ decrement count loop
20206 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
20207 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20208 0<> WHILE \ ----> out of loop ----+
20209 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20211 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
20212 CMP Y,X \ 1 | cycle time out of bound ?
20213 U>= IF \ 2 ^ | yes:
20214 BIC #$30,&RC5_TIM_CTL \ | | stop timer
20215 GOTO BW1 \ | | quit on truncated RC5 message
20217 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
20219 REPEAT \ ----> loop back --+ | with X = new RC5_period value
20220 \ ******************************\ |
20221 \ RC5_SampleEndOf: \ <---------------------+
20222 \ ******************************\
20223 BIC #$30,&RC5_TIM_CTL \ stop timer
20224 \ ******************************\
20225 \ RC5_ComputeNewRC5word \
20226 \ ******************************\
20227 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
20228 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
20229 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
20230 \ ******************************\
20231 \ RC5_ComputeC6bit \
20232 \ ******************************\
20233 BIT #BIT14,T \ test /C6 bit in T
20234 0= IF BIS #BIT6,X \ set C6 bit in X
20235 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
20236 \ ******************************\
20237 \ RC5_CommandByteIsDone \ -- BASE RC5_code
20238 \ ******************************\
20239 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20240 \ ******************************\
20241 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
20242 XOR @RSP,T \ (new XOR old) Toggle bits
20243 BIT #UF10,T \ repeated RC5_command ?
20244 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
20245 XOR #UF10,0(RSP) \ 5 toggle bit memory
20246 \ ******************************\
20247 \ Display IR_RC5 code \
20248 \ ******************************\
20249 SUB #8,PSP \ TOS -- x x x x TOS
20250 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
20251 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
20252 MOV #$10,&BASEADR \ set hexadecimal base
20253 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
20254 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
20255 LO2HI \ switch from assembler to FORTH
20256 LCD_CLEAR \ set LCD cursor at home
20257 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
20258 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
20259 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
20260 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
20261 HI2LO \ -- switch from FORTH to assembler
20262 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
20263 MOV @PSP+,TOS \ -- TOS
20267 \ ------------------------------\
20269 \ ------------------------------\
20271 \ ... \ insert here your background task
20274 CALL &RXON \ comment this line to disable TERMINAL
20276 \ ******************************\
20277 \ here start all interrupts \
20278 \ ******************************\
20279 \ here return all interrupts \
20280 \ ******************************\
20284 \ ------------------------------\
20285 CODE STOP \ stops multitasking, must to be used before downloading app
20286 \ ------------------------------\
20287 \ restore default action of primary DEFERred word SLEEP (assembly version)
20288 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
20289 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
20290 MOV X,-2(X) \ restore the default background
20291 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
20292 ['] WARM >BODY IS WARM \ restore the default WARM
20294 ." RC5toLCD is removed. type START to restart"
20295 COLD \ performs reset to reset all interrupt vectors.
20298 \ ------------------------------\
20299 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
20300 \ ------------------------------\
20301 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
20302 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20303 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20304 \ -- \ID input divider \ 10 = /4
20305 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20306 \ - \TBCLR TimerB Clear
20309 \ -------------------------------\
20310 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20311 \ -- \CM Capture Mode
20316 \ --- \OUTMOD \ 011 = set/reset
20322 \ -------------------------------\
20324 \ -------------------------------\
20326 \ ------------------------------\
20327 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20328 \ ------------------------------\
20329 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20330 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20331 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
20332 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20334 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
20335 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20337 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
20338 \ ------------------------------\
20339 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20340 \ ------------------------------\
20341 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
20342 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20343 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20344 \ ------------------------------\
20345 BIS.B #LCDVo,&LCDVo_DIR \
20346 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
20347 \ ------------------------------\
20348 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20349 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20350 \ ------------------------------\
20351 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20352 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20353 \ ******************************\
20355 \ ******************************\
20356 BIS.B #RC5,&IR_IE \ enable RC5_Int
20357 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20358 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20359 \ ******************************\
20360 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20361 \ ******************************\
20362 \ %01 0001 0100 \ TAxCTL
20363 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
20364 \ -- \ ID divided by 1
20365 \ -- \ MC MODE = up to TAxCCRn
20366 \ - \ TACLR clear timer count
20369 \ ------------------------------\
20370 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
20371 \ ------------------------------\
20373 \ --- \ TAIDEX pre divisor
20374 \ ------------------------------\
20375 \ %0000 0000 0000 0101 \ TAxCCR0
20376 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20377 \ ------------------------------\
20378 \ %0000 0000 0001 0000 \ TAxCCTL0
20379 \ - \ CAP capture/compare mode = compare
20382 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
20383 \ ------------------------------\
20384 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
20385 \ ------------------------------\
20386 \ define LPM mode for ACCEPT \
20387 \ ------------------------------\
20388 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20389 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20390 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20391 \ ------------------------------\
20393 \ ------------------------------\
20394 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
20395 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
20396 \ ------------------------------\
20397 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
20398 \ ------------------------------\
20399 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
20400 \ CMP #2,Y \ Power_ON event
20401 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
20403 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
20405 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
20407 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
20409 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
20410 \ ------------------------------\
20412 \ ------------------------------\
20414 \ ------------------------------\
20415 #1000 20_US \ 1- wait 20 ms
20416 %011 TOP_LCD \ 2- send DB5=DB4=1
20417 #205 20_US \ 3- wait 4,1 ms
20418 %011 TOP_LCD \ 4- send again DB5=DB4=1
20419 #5 20_US \ 5- wait 0,1 ms
20420 %011 TOP_LCD \ 6- send again again DB5=DB4=1
20421 #2 20_US \ wait 40 us = LCD cycle
20422 %010 TOP_LCD \ 7- send DB5=1 DB4=0
20423 #2 20_US \ wait 40 us = LCD cycle
20424 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20425 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20426 LCD_CLEAR \ 10- "LCD_Clear"
20427 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20428 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20429 LCD_CLEAR \ 10- "LCD_Clear"
20430 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20431 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20432 CR ." I love you" \ display message on LCD
20433 ['] CR >BODY IS CR \ CR executes its default value
20434 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
20435 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20436 ABORT \ ...and end APP_INIT with ABORT, no return.
20439 \ ------------------------------\
20440 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
20441 \ ------------------------------\
20442 MOV #SLEEP,X \ replace default background process
20443 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
20444 MOV #WARM,X \ replace default WARM
20445 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
20446 MOV X,PC \ then execute it
20449 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
20453 CODE 20_US \ n -- n * 20 us
20454 BEGIN \ here we presume that LCD_TIM_IFG = 1...
20456 BIT #1,&LCD_TIM_CTL \ 3
20457 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
20458 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
20460 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
20465 CODE TOP_LCD \ LCD Sample
20466 \ \ if write : %xxxxWWWW --
20467 \ \ if read : -- %0000RRRR
20468 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20469 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20470 0= IF \ write LCD bits pattern
20471 AND.B #LCD_DB,TOS \
20472 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20473 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20476 THEN \ read LCD bits pattern
20479 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20480 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20481 AND.B #LCD_DB,TOS \
20485 CODE LCD_WRC \ char -- Write Char
20486 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20488 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20489 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20490 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20491 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20492 COLON \ high level word starts here
20493 TOP_LCD 2 20_US \ write high nibble first
20497 CODE LCD_WRF \ func -- Write Fonction
20498 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20502 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
20503 : LCD_HOME $02 LCD_WRF 100 20_us ;
20505 \ [UNDEFINED] OR [IF]
20507 \ \ https://forth-standard.org/standard/core/OR
20508 \ \ C OR x1 x2 -- x3 logical OR
20516 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
20517 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
20518 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
20519 \ : LCD_FN_SET $20 OR LCD_WrF ;
20520 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
20521 \ : LCD_GOTO $80 OR LCD_WrF ;
20524 \ CODE LCD_RDS \ -- status Read Status
20525 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20526 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20527 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20528 \ COLON \ starts a FORTH word
20529 \ TOP_LCD 2 20_us \ -- %0000HHHH
20530 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20531 \ HI2LO \ switch from FORTH to assembler
20532 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20533 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20534 \ MOV @RSP+,IP \ restore IP saved by COLON
20538 \ CODE LCD_RDC \ -- char Read Char
20539 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20544 \ ******************************\
20545 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20546 \ ******************************\
20547 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20548 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20549 BIT.B #SW2,&SW2_IN \ test switch S2
20550 0= IF \ case of switch S2 pressed
20551 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20553 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20556 BIT.B #SW1,&SW1_IN \ test switch S1 input
20557 0= IF \ case of Switch S1 pressed
20558 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20560 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20564 BW1 \ from quit on truncated RC5 message, repeated RC5 command
20568 \ ******************************\
20569 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20570 \ ******************************\
20571 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20572 \ ******************************\
20573 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20574 \ \ SMclock = 8|16|24 MHz
20575 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20576 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20577 \ \ SR(9)=new Toggle bit memory (ADD on)
20578 \ ******************************\
20579 \ RC5_FirstStartBitHalfCycle: \
20580 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20581 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20582 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20583 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20585 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20586 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20588 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20589 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20591 MOV #1778,X \ RC5_Period * 1us
20592 MOV #14,W \ count of loop
20594 \ ******************************\
20595 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
20596 \ ******************************\ |
20597 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20598 \ RC5_Compute_3/4_Period: \ |
20599 RRUM #1,X \ X=1/2 cycle |
20602 ADD X,Y \ Y=3/4 cycle
20603 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
20605 \ ******************************\
20606 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20607 \ ******************************\
20608 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20609 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
20610 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20611 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20612 SUB #1,W \ decrement count loop
20613 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
20614 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20615 0<> WHILE \ ----> out of loop ----+
20616 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20618 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
20619 CMP Y,X \ 1 | cycle time out of bound ?
20620 U>= IF \ 2 ^ | yes:
20621 BIC #$30,&RC5_TIM_CTL \ | | stop timer
20622 GOTO BW1 \ | | quit on truncated RC5 message
20624 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
20626 REPEAT \ ----> loop back --+ | with X = new RC5_period value
20627 \ ******************************\ |
20628 \ RC5_SampleEndOf: \ <---------------------+
20629 \ ******************************\
20630 BIC #$30,&RC5_TIM_CTL \ stop timer
20631 \ ******************************\
20632 \ RC5_ComputeNewRC5word \
20633 \ ******************************\
20634 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
20635 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
20636 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
20637 \ ******************************\
20638 \ RC5_ComputeC6bit \
20639 \ ******************************\
20640 BIT #BIT14,T \ test /C6 bit in T
20641 0= IF BIS #BIT6,X \ set C6 bit in X
20642 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
20643 \ ******************************\
20644 \ RC5_CommandByteIsDone \ -- BASE RC5_code
20645 \ ******************************\
20646 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20647 \ ******************************\
20648 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
20649 XOR @RSP,T \ (new XOR old) Toggle bits
20650 BIT #UF10,T \ repeated RC5_command ?
20651 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
20652 XOR #UF10,0(RSP) \ 5 toggle bit memory
20653 \ ******************************\
20654 \ Display IR_RC5 code \
20655 \ ******************************\
20656 SUB #8,PSP \ TOS -- x x x x TOS
20657 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
20658 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
20659 MOV #$10,&BASEADR \ set hexadecimal base
20660 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
20661 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
20662 LO2HI \ switch from assembler to FORTH
20663 LCD_CLEAR \ set LCD cursor at home
20664 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
20665 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
20666 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
20667 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
20668 HI2LO \ -- switch from FORTH to assembler
20669 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
20670 MOV @PSP+,TOS \ -- TOS
20674 \ ------------------------------\
20676 \ ------------------------------\
20678 \ ... \ insert here your background task
20681 CALL &RXON \ comment this line to disable TERMINAL
20683 \ ******************************\
20684 \ here start all interrupts \
20685 \ ******************************\
20686 \ here return all interrupts \
20687 \ ******************************\
20691 \ ------------------------------\
20692 CODE STOP \ stops multitasking, must to be used before downloading app
20693 \ ------------------------------\
20694 \ restore default action of primary DEFERred word SLEEP (assembly version)
20695 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
20696 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
20697 MOV X,-2(X) \ restore the default background
20698 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
20699 ['] WARM >BODY IS WARM \ restore the default WARM
20701 ." RC5toLCD is removed. type START to restart"
20702 COLD \ performs reset to reset all interrupt vectors.
20705 \ ------------------------------\
20706 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
20707 \ ------------------------------\
20708 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
20709 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20710 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20711 \ -- \ID input divider \ 10 = /4
20712 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20713 \ - \TBCLR TimerB Clear
20716 \ -------------------------------\
20717 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20718 \ -- \CM Capture Mode
20723 \ --- \OUTMOD \ 011 = set/reset
20729 \ -------------------------------\
20731 \ -------------------------------\
20733 \ ------------------------------\
20734 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20735 \ ------------------------------\
20736 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20737 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20738 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
20739 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20741 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
20742 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20744 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
20745 \ ------------------------------\
20746 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20747 \ ------------------------------\
20748 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
20749 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20750 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20751 \ ------------------------------\
20752 BIS.B #LCDVo,&LCDVo_DIR \
20753 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
20754 \ ------------------------------\
20755 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20756 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20757 \ ------------------------------\
20758 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20759 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20760 \ ******************************\
20762 \ ******************************\
20763 BIS.B #RC5,&IR_IE \ enable RC5_Int
20764 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20765 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20766 \ ******************************\
20767 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20768 \ ******************************\
20769 \ %01 0001 0100 \ TAxCTL
20770 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
20771 \ -- \ ID divided by 1
20772 \ -- \ MC MODE = up to TAxCCRn
20773 \ - \ TACLR clear timer count
20776 \ ------------------------------\
20777 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
20778 \ ------------------------------\
20780 \ --- \ TAIDEX pre divisor
20781 \ ------------------------------\
20782 \ %0000 0000 0000 0101 \ TAxCCR0
20783 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20784 \ ------------------------------\
20785 \ %0000 0000 0001 0000 \ TAxCCTL0
20786 \ - \ CAP capture/compare mode = compare
20789 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
20790 \ ------------------------------\
20791 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
20792 \ ------------------------------\
20793 \ define LPM mode for ACCEPT \
20794 \ ------------------------------\
20795 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20796 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20797 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20798 \ ------------------------------\
20800 \ ------------------------------\
20801 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
20802 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
20803 \ ------------------------------\
20804 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
20805 \ ------------------------------\
20806 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
20807 \ CMP #2,Y \ Power_ON event
20808 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
20810 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
20812 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
20814 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
20816 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
20817 \ ------------------------------\
20819 \ ------------------------------\
20821 \ ------------------------------\
20822 #1000 20_US \ 1- wait 20 ms
20823 %011 TOP_LCD \ 2- send DB5=DB4=1
20824 #205 20_US \ 3- wait 4,1 ms
20825 %011 TOP_LCD \ 4- send again DB5=DB4=1
20826 #5 20_US \ 5- wait 0,1 ms
20827 %011 TOP_LCD \ 6- send again again DB5=DB4=1
20828 #2 20_US \ wait 40 us = LCD cycle
20829 %010 TOP_LCD \ 7- send DB5=1 DB4=0
20830 #2 20_US \ wait 40 us = LCD cycle
20831 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20832 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20833 LCD_CLEAR \ 10- "LCD_Clear"
20834 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20835 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20836 LCD_CLEAR \ 10- "LCD_Clear"
20837 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20838 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20839 CR ." I love you" \ display message on LCD
20840 ['] CR >BODY IS CR \ CR executes its default value
20841 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
20842 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20843 ABORT \ ...and end APP_INIT with ABORT, no return.
20846 \ ------------------------------\
20847 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
20848 \ ------------------------------\
20849 MOV #SLEEP,X \ replace default background process
20850 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
20851 MOV #WARM,X \ replace default WARM
20852 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
20853 MOV X,PC \ then execute it
20856 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
20860 CODE 20_US \ n -- n * 20 us
20861 BEGIN \ here we presume that LCD_TIM_IFG = 1...
20863 BIT #1,&LCD_TIM_CTL \ 3
20864 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
20865 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
20867 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
20872 CODE TOP_LCD \ LCD Sample
20873 \ \ if write : %xxxxWWWW --
20874 \ \ if read : -- %0000RRRR
20875 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20876 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20877 0= IF \ write LCD bits pattern
20878 AND.B #LCD_DB,TOS \
20879 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20880 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20883 THEN \ read LCD bits pattern
20886 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20887 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20888 AND.B #LCD_DB,TOS \
20892 CODE LCD_WRC \ char -- Write Char
20893 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20895 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20896 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20897 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20898 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20899 COLON \ high level word starts here
20900 TOP_LCD 2 20_US \ write high nibble first
20904 CODE LCD_WRF \ func -- Write Fonction
20905 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20909 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
20910 : LCD_HOME $02 LCD_WRF 100 20_us ;
20912 \ [UNDEFINED] OR [IF]
20914 \ \ https://forth-standard.org/standard/core/OR
20915 \ \ C OR x1 x2 -- x3 logical OR
20923 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
20924 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
20925 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
20926 \ : LCD_FN_SET $20 OR LCD_WrF ;
20927 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
20928 \ : LCD_GOTO $80 OR LCD_WrF ;
20931 \ CODE LCD_RDS \ -- status Read Status
20932 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20933 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20934 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20935 \ COLON \ starts a FORTH word
20936 \ TOP_LCD 2 20_us \ -- %0000HHHH
20937 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20938 \ HI2LO \ switch from FORTH to assembler
20939 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20940 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20941 \ MOV @RSP+,IP \ restore IP saved by COLON
20945 \ CODE LCD_RDC \ -- char Read Char
20946 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20951 \ ******************************\
20952 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20953 \ ******************************\
20954 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20955 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20956 BIT.B #SW2,&SW2_IN \ test switch S2
20957 0= IF \ case of switch S2 pressed
20958 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20960 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20963 BIT.B #SW1,&SW1_IN \ test switch S1 input
20964 0= IF \ case of Switch S1 pressed
20965 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20967 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20971 BW1 \ from quit on truncated RC5 message, repeated RC5 command
20975 \ ******************************\
20976 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20977 \ ******************************\
20978 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20979 \ ******************************\
20980 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20981 \ \ SMclock = 8|16|24 MHz
20982 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20983 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20984 \ \ SR(9)=new Toggle bit memory (ADD on)
20985 \ ******************************\
20986 \ RC5_FirstStartBitHalfCycle: \
20987 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20988 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20989 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20990 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20992 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20993 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20995 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20996 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20998 MOV #1778,X \ RC5_Period * 1us
20999 MOV #14,W \ count of loop
21001 \ ******************************\
21002 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
21003 \ ******************************\ |
21004 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21005 \ RC5_Compute_3/4_Period: \ |
21006 RRUM #1,X \ X=1/2 cycle |
21009 ADD X,Y \ Y=3/4 cycle
21010 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
21012 \ ******************************\
21013 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21014 \ ******************************\
21015 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21016 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
21017 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21018 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21019 SUB #1,W \ decrement count loop
21020 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
21021 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21022 0<> WHILE \ ----> out of loop ----+
21023 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21025 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
21026 CMP Y,X \ 1 | cycle time out of bound ?
21027 U>= IF \ 2 ^ | yes:
21028 BIC #$30,&RC5_TIM_CTL \ | | stop timer
21029 GOTO BW1 \ | | quit on truncated RC5 message
21031 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
21033 REPEAT \ ----> loop back --+ | with X = new RC5_period value
21034 \ ******************************\ |
21035 \ RC5_SampleEndOf: \ <---------------------+
21036 \ ******************************\
21037 BIC #$30,&RC5_TIM_CTL \ stop timer
21038 \ ******************************\
21039 \ RC5_ComputeNewRC5word \
21040 \ ******************************\
21041 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
21042 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
21043 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
21044 \ ******************************\
21045 \ RC5_ComputeC6bit \
21046 \ ******************************\
21047 BIT #BIT14,T \ test /C6 bit in T
21048 0= IF BIS #BIT6,X \ set C6 bit in X
21049 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
21050 \ ******************************\
21051 \ RC5_CommandByteIsDone \ -- BASE RC5_code
21052 \ ******************************\
21053 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21054 \ ******************************\
21055 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
21056 XOR @RSP,T \ (new XOR old) Toggle bits
21057 BIT #UF10,T \ repeated RC5_command ?
21058 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
21059 XOR #UF10,0(RSP) \ 5 toggle bit memory
21060 \ ******************************\
21061 \ Display IR_RC5 code \
21062 \ ******************************\
21063 SUB #8,PSP \ TOS -- x x x x TOS
21064 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
21065 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
21066 MOV #$10,&BASEADR \ set hexadecimal base
21067 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
21068 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
21069 LO2HI \ switch from assembler to FORTH
21070 LCD_CLEAR \ set LCD cursor at home
21071 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
21072 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
21073 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
21074 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
21075 HI2LO \ -- switch from FORTH to assembler
21076 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
21077 MOV @PSP+,TOS \ -- TOS
21081 \ ------------------------------\
21083 \ ------------------------------\
21085 \ ... \ insert here your background task
21088 CALL &RXON \ comment this line to disable TERMINAL
21090 \ ******************************\
21091 \ here start all interrupts \
21092 \ ******************************\
21093 \ here return all interrupts \
21094 \ ******************************\
21098 \ ------------------------------\
21099 CODE STOP \ stops multitasking, must to be used before downloading app
21100 \ ------------------------------\
21101 \ restore default action of primary DEFERred word SLEEP (assembly version)
21102 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
21103 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
21104 MOV X,-2(X) \ restore the default background
21105 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
21106 ['] WARM >BODY IS WARM \ restore the default WARM
21108 ." RC5toLCD is removed. type START to restart"
21109 COLD \ performs reset to reset all interrupt vectors.
21112 \ ------------------------------\
21113 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
21114 \ ------------------------------\
21115 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
21116 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21117 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21118 \ -- \ID input divider \ 10 = /4
21119 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21120 \ - \TBCLR TimerB Clear
21123 \ -------------------------------\
21124 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21125 \ -- \CM Capture Mode
21130 \ --- \OUTMOD \ 011 = set/reset
21136 \ -------------------------------\
21138 \ -------------------------------\
21140 \ ------------------------------\
21141 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21142 \ ------------------------------\
21143 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21144 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21145 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
21146 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21148 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
21149 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21151 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
21152 \ ------------------------------\
21153 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21154 \ ------------------------------\
21155 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
21156 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21157 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21158 \ ------------------------------\
21159 BIS.B #LCDVo,&LCDVo_DIR \
21160 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
21161 \ ------------------------------\
21162 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21163 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21164 \ ------------------------------\
21165 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21166 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21167 \ ******************************\
21169 \ ******************************\
21170 BIS.B #RC5,&IR_IE \ enable RC5_Int
21171 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21172 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21173 \ ******************************\
21174 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21175 \ ******************************\
21176 \ %01 0001 0100 \ TAxCTL
21177 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
21178 \ -- \ ID divided by 1
21179 \ -- \ MC MODE = up to TAxCCRn
21180 \ - \ TACLR clear timer count
21183 \ ------------------------------\
21184 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
21185 \ ------------------------------\
21187 \ --- \ TAIDEX pre divisor
21188 \ ------------------------------\
21189 \ %0000 0000 0000 0101 \ TAxCCR0
21190 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
21191 \ ------------------------------\
21192 \ %0000 0000 0001 0000 \ TAxCCTL0
21193 \ - \ CAP capture/compare mode = compare
21196 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
21197 \ ------------------------------\
21198 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21199 \ ------------------------------\
21200 \ define LPM mode for ACCEPT \
21201 \ ------------------------------\
21202 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21203 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21204 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21205 \ ------------------------------\
21207 \ ------------------------------\
21208 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
21209 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
21210 \ ------------------------------\
21211 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
21212 \ ------------------------------\
21213 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
21214 \ CMP #2,Y \ Power_ON event
21215 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
21217 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
21219 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
21221 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
21223 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
21224 \ ------------------------------\
21226 \ ------------------------------\
21228 \ ------------------------------\
21229 #1000 20_US \ 1- wait 20 ms
21230 %011 TOP_LCD \ 2- send DB5=DB4=1
21231 #205 20_US \ 3- wait 4,1 ms
21232 %011 TOP_LCD \ 4- send again DB5=DB4=1
21233 #5 20_US \ 5- wait 0,1 ms
21234 %011 TOP_LCD \ 6- send again again DB5=DB4=1
21235 #2 20_US \ wait 40 us = LCD cycle
21236 %010 TOP_LCD \ 7- send DB5=1 DB4=0
21237 #2 20_US \ wait 40 us = LCD cycle
21238 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21239 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21240 LCD_CLEAR \ 10- "LCD_Clear"
21241 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21242 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21243 LCD_CLEAR \ 10- "LCD_Clear"
21244 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21245 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21246 CR ." I love you" \ display message on LCD
21247 ['] CR >BODY IS CR \ CR executes its default value
21248 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
21249 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21250 ABORT \ ...and end APP_INIT with ABORT, no return.
21253 \ ------------------------------\
21254 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
21255 \ ------------------------------\
21256 MOV #SLEEP,X \ replace default background process
21257 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
21258 MOV #WARM,X \ replace default WARM
21259 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
21260 MOV X,PC \ then execute it
21263 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
21267 CODE 20_US \ n -- n * 20 us
21268 BEGIN \ here we presume that LCD_TIM_IFG = 1...
21270 BIT #1,&LCD_TIM_CTL \ 3
21271 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
21272 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
21274 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
21279 CODE TOP_LCD \ LCD Sample
21280 \ \ if write : %xxxxWWWW --
21281 \ \ if read : -- %0000RRRR
21282 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21283 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21284 0= IF \ write LCD bits pattern
21285 AND.B #LCD_DB,TOS \
21286 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21287 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21290 THEN \ read LCD bits pattern
21293 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21294 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21295 AND.B #LCD_DB,TOS \
21299 CODE LCD_WRC \ char -- Write Char
21300 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21302 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21303 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21304 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21305 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21306 COLON \ high level word starts here
21307 TOP_LCD 2 20_US \ write high nibble first
21311 CODE LCD_WRF \ func -- Write Fonction
21312 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21316 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
21317 : LCD_HOME $02 LCD_WRF 100 20_us ;
21319 \ [UNDEFINED] OR [IF]
21321 \ \ https://forth-standard.org/standard/core/OR
21322 \ \ C OR x1 x2 -- x3 logical OR
21330 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
21331 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
21332 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
21333 \ : LCD_FN_SET $20 OR LCD_WrF ;
21334 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
21335 \ : LCD_GOTO $80 OR LCD_WrF ;
21338 \ CODE LCD_RDS \ -- status Read Status
21339 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21340 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21341 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21342 \ COLON \ starts a FORTH word
21343 \ TOP_LCD 2 20_us \ -- %0000HHHH
21344 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21345 \ HI2LO \ switch from FORTH to assembler
21346 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21347 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21348 \ MOV @RSP+,IP \ restore IP saved by COLON
21352 \ CODE LCD_RDC \ -- char Read Char
21353 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21358 \ ******************************\
21359 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21360 \ ******************************\
21361 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21362 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
21363 BIT.B #SW2,&SW2_IN \ test switch S2
21364 0= IF \ case of switch S2 pressed
21365 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21367 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
21370 BIT.B #SW1,&SW1_IN \ test switch S1 input
21371 0= IF \ case of Switch S1 pressed
21372 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21374 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21378 BW1 \ from quit on truncated RC5 message, repeated RC5 command
21382 \ ******************************\
21383 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21384 \ ******************************\
21385 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21386 \ ******************************\
21387 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21388 \ \ SMclock = 8|16|24 MHz
21389 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
21390 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
21391 \ \ SR(9)=new Toggle bit memory (ADD on)
21392 \ ******************************\
21393 \ RC5_FirstStartBitHalfCycle: \
21394 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
21395 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21396 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
21397 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
21399 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
21400 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
21402 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
21403 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
21405 MOV #1778,X \ RC5_Period * 1us
21406 MOV #14,W \ count of loop
21408 \ ******************************\
21409 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
21410 \ ******************************\ |
21411 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21412 \ RC5_Compute_3/4_Period: \ |
21413 RRUM #1,X \ X=1/2 cycle |
21416 ADD X,Y \ Y=3/4 cycle
21417 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
21419 \ ******************************\
21420 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21421 \ ******************************\
21422 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21423 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
21424 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21425 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21426 SUB #1,W \ decrement count loop
21427 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
21428 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21429 0<> WHILE \ ----> out of loop ----+
21430 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21432 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
21433 CMP Y,X \ 1 | cycle time out of bound ?
21434 U>= IF \ 2 ^ | yes:
21435 BIC #$30,&RC5_TIM_CTL \ | | stop timer
21436 GOTO BW1 \ | | quit on truncated RC5 message
21438 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
21440 REPEAT \ ----> loop back --+ | with X = new RC5_period value
21441 \ ******************************\ |
21442 \ RC5_SampleEndOf: \ <---------------------+
21443 \ ******************************\
21444 BIC #$30,&RC5_TIM_CTL \ stop timer
21445 \ ******************************\
21446 \ RC5_ComputeNewRC5word \
21447 \ ******************************\
21448 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
21449 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
21450 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
21451 \ ******************************\
21452 \ RC5_ComputeC6bit \
21453 \ ******************************\
21454 BIT #BIT14,T \ test /C6 bit in T
21455 0= IF BIS #BIT6,X \ set C6 bit in X
21456 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
21457 \ ******************************\
21458 \ RC5_CommandByteIsDone \ -- BASE RC5_code
21459 \ ******************************\
21460 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21461 \ ******************************\
21462 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
21463 XOR @RSP,T \ (new XOR old) Toggle bits
21464 BIT #UF10,T \ repeated RC5_command ?
21465 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
21466 XOR #UF10,0(RSP) \ 5 toggle bit memory
21467 \ ******************************\
21468 \ Display IR_RC5 code \
21469 \ ******************************\
21470 SUB #8,PSP \ TOS -- x x x x TOS
21471 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
21472 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
21473 MOV #$10,&BASEADR \ set hexadecimal base
21474 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
21475 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
21476 LO2HI \ switch from assembler to FORTH
21477 LCD_CLEAR \ set LCD cursor at home
21478 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
21479 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
21480 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
21481 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
21482 HI2LO \ -- switch from FORTH to assembler
21483 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
21484 MOV @PSP+,TOS \ -- TOS
21488 \ ------------------------------\
21490 \ ------------------------------\
21492 \ ... \ insert here your background task
21495 CALL &RXON \ comment this line to disable TERMINAL
21497 \ ******************************\
21498 \ here start all interrupts \
21499 \ ******************************\
21500 \ here return all interrupts \
21501 \ ******************************\
21505 \ ------------------------------\
21506 CODE STOP \ stops multitasking, must to be used before downloading app
21507 \ ------------------------------\
21508 \ restore default action of primary DEFERred word SLEEP (assembly version)
21509 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
21510 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
21511 MOV X,-2(X) \ restore the default background
21512 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
21513 ['] WARM >BODY IS WARM \ restore the default WARM
21515 ." RC5toLCD is removed. type START to restart"
21516 COLD \ performs reset to reset all interrupt vectors.
21519 \ ------------------------------\
21520 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
21521 \ ------------------------------\
21522 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
21523 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21524 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21525 \ -- \ID input divider \ 10 = /4
21526 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21527 \ - \TBCLR TimerB Clear
21530 \ -------------------------------\
21531 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21532 \ -- \CM Capture Mode
21537 \ --- \OUTMOD \ 011 = set/reset
21543 \ -------------------------------\
21545 \ -------------------------------\
21547 \ ------------------------------\
21548 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21549 \ ------------------------------\
21550 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21551 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21552 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
21553 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21555 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
21556 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21558 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
21559 \ ------------------------------\
21560 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21561 \ ------------------------------\
21562 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
21563 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21564 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21565 \ ------------------------------\
21566 BIS.B #LCDVo,&LCDVo_DIR \
21567 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
21568 \ ------------------------------\
21569 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21570 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21571 \ ------------------------------\
21572 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21573 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21574 \ ******************************\
21576 \ ******************************\
21577 BIS.B #RC5,&IR_IE \ enable RC5_Int
21578 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21579 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21580 \ ******************************\
21581 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21582 \ ******************************\
21583 \ %01 0001 0100 \ TAxCTL
21584 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
21585 \ -- \ ID divided by 1
21586 \ -- \ MC MODE = up to TAxCCRn
21587 \ - \ TACLR clear timer count
21590 \ ------------------------------\
21591 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
21592 \ ------------------------------\
21594 \ --- \ TAIDEX pre divisor
21595 \ ------------------------------\
21596 \ %0000 0000 0000 0101 \ TAxCCR0
21597 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
21598 \ ------------------------------\
21599 \ %0000 0000 0001 0000 \ TAxCCTL0
21600 \ - \ CAP capture/compare mode = compare
21603 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
21604 \ ------------------------------\
21605 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21606 \ ------------------------------\
21607 \ define LPM mode for ACCEPT \
21608 \ ------------------------------\
21609 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21610 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21611 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21612 \ ------------------------------\
21614 \ ------------------------------\
21615 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
21616 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
21617 \ ------------------------------\
21618 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
21619 \ ------------------------------\
21620 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
21621 \ CMP #2,Y \ Power_ON event
21622 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
21624 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
21626 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
21628 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
21630 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
21631 \ ------------------------------\
21633 \ ------------------------------\
21635 \ ------------------------------\
21636 #1000 20_US \ 1- wait 20 ms
21637 %011 TOP_LCD \ 2- send DB5=DB4=1
21638 #205 20_US \ 3- wait 4,1 ms
21639 %011 TOP_LCD \ 4- send again DB5=DB4=1
21640 #5 20_US \ 5- wait 0,1 ms
21641 %011 TOP_LCD \ 6- send again again DB5=DB4=1
21642 #2 20_US \ wait 40 us = LCD cycle
21643 %010 TOP_LCD \ 7- send DB5=1 DB4=0
21644 #2 20_US \ wait 40 us = LCD cycle
21645 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21646 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21647 LCD_CLEAR \ 10- "LCD_Clear"
21648 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21649 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21650 LCD_CLEAR \ 10- "LCD_Clear"
21651 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21652 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21653 CR ." I love you" \ display message on LCD
21654 ['] CR >BODY IS CR \ CR executes its default value
21655 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
21656 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21657 ABORT \ ...and end APP_INIT with ABORT, no return.
21660 \ ------------------------------\
21661 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
21662 \ ------------------------------\
21663 MOV #SLEEP,X \ replace default background process
21664 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
21665 MOV #WARM,X \ replace default WARM
21666 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
21667 MOV X,PC \ then execute it
21670 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
21674 CODE 20_US \ n -- n * 20 us
21675 BEGIN \ here we presume that LCD_TIM_IFG = 1...
21677 BIT #1,&LCD_TIM_CTL \ 3
21678 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
21679 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
21681 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
21686 CODE TOP_LCD \ LCD Sample
21687 \ \ if write : %xxxxWWWW --
21688 \ \ if read : -- %0000RRRR
21689 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21690 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21691 0= IF \ write LCD bits pattern
21692 AND.B #LCD_DB,TOS \
21693 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21694 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21697 THEN \ read LCD bits pattern
21700 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21701 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21702 AND.B #LCD_DB,TOS \
21706 CODE LCD_WRC \ char -- Write Char
21707 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21709 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21710 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21711 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21712 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21713 COLON \ high level word starts here
21714 TOP_LCD 2 20_US \ write high nibble first
21718 CODE LCD_WRF \ func -- Write Fonction
21719 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21723 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
21724 : LCD_HOME $02 LCD_WRF 100 20_us ;
21726 \ [UNDEFINED] OR [IF]
21728 \ \ https://forth-standard.org/standard/core/OR
21729 \ \ C OR x1 x2 -- x3 logical OR
21737 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
21738 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
21739 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
21740 \ : LCD_FN_SET $20 OR LCD_WrF ;
21741 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
21742 \ : LCD_GOTO $80 OR LCD_WrF ;
21745 \ CODE LCD_RDS \ -- status Read Status
21746 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21747 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21748 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21749 \ COLON \ starts a FORTH word
21750 \ TOP_LCD 2 20_us \ -- %0000HHHH
21751 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21752 \ HI2LO \ switch from FORTH to assembler
21753 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21754 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21755 \ MOV @RSP+,IP \ restore IP saved by COLON
21759 \ CODE LCD_RDC \ -- char Read Char
21760 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21765 \ ******************************\
21766 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21767 \ ******************************\
21768 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21769 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
21770 BIT.B #SW2,&SW2_IN \ test switch S2
21771 0= IF \ case of switch S2 pressed
21772 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21774 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
21777 BIT.B #SW1,&SW1_IN \ test switch S1 input
21778 0= IF \ case of Switch S1 pressed
21779 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21781 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21785 BW1 \ from quit on truncated RC5 message, repeated RC5 command
21789 \ ******************************\
21790 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21791 \ ******************************\
21792 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21793 \ ******************************\
21794 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21795 \ \ SMclock = 8|16|24 MHz
21796 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
21797 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
21798 \ \ SR(9)=new Toggle bit memory (ADD on)
21799 \ ******************************\
21800 \ RC5_FirstStartBitHalfCycle: \
21801 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
21802 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21803 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
21804 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
21806 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
21807 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
21809 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
21810 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
21812 MOV #1778,X \ RC5_Period * 1us
21813 MOV #14,W \ count of loop
21815 \ ******************************\
21816 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
21817 \ ******************************\ |
21818 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21819 \ RC5_Compute_3/4_Period: \ |
21820 RRUM #1,X \ X=1/2 cycle |
21823 ADD X,Y \ Y=3/4 cycle
21824 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
21826 \ ******************************\
21827 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21828 \ ******************************\
21829 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21830 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
21831 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21832 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21833 SUB #1,W \ decrement count loop
21834 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
21835 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21836 0<> WHILE \ ----> out of loop ----+
21837 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21839 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
21840 CMP Y,X \ 1 | cycle time out of bound ?
21841 U>= IF \ 2 ^ | yes:
21842 BIC #$30,&RC5_TIM_CTL \ | | stop timer
21843 GOTO BW1 \ | | quit on truncated RC5 message
21845 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
21847 REPEAT \ ----> loop back --+ | with X = new RC5_period value
21848 \ ******************************\ |
21849 \ RC5_SampleEndOf: \ <---------------------+
21850 \ ******************************\
21851 BIC #$30,&RC5_TIM_CTL \ stop timer
21852 \ ******************************\
21853 \ RC5_ComputeNewRC5word \
21854 \ ******************************\
21855 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
21856 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
21857 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
21858 \ ******************************\
21859 \ RC5_ComputeC6bit \
21860 \ ******************************\
21861 BIT #BIT14,T \ test /C6 bit in T
21862 0= IF BIS #BIT6,X \ set C6 bit in X
21863 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
21864 \ ******************************\
21865 \ RC5_CommandByteIsDone \ -- BASE RC5_code
21866 \ ******************************\
21867 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21868 \ ******************************\
21869 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
21870 XOR @RSP,T \ (new XOR old) Toggle bits
21871 BIT #UF10,T \ repeated RC5_command ?
21872 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
21873 XOR #UF10,0(RSP) \ 5 toggle bit memory
21874 \ ******************************\
21875 \ Display IR_RC5 code \
21876 \ ******************************\
21877 SUB #8,PSP \ TOS -- x x x x TOS
21878 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
21879 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
21880 MOV #$10,&BASEADR \ set hexadecimal base
21881 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
21882 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
21883 LO2HI \ switch from assembler to FORTH
21884 LCD_CLEAR \ set LCD cursor at home
21885 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
21886 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
21887 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
21888 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
21889 HI2LO \ -- switch from FORTH to assembler
21890 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
21891 MOV @PSP+,TOS \ -- TOS
21895 \ ------------------------------\
21897 \ ------------------------------\
21899 \ ... \ insert here your background task
21902 CALL &RXON \ comment this line to disable TERMINAL
21904 \ ******************************\
21905 \ here start all interrupts \
21906 \ ******************************\
21907 \ here return all interrupts \
21908 \ ******************************\
21912 \ ------------------------------\
21913 CODE STOP \ stops multitasking, must to be used before downloading app
21914 \ ------------------------------\
21915 \ restore default action of primary DEFERred word SLEEP (assembly version)
21916 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
21917 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
21918 MOV X,-2(X) \ restore the default background
21919 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
21920 ['] WARM >BODY IS WARM \ restore the default WARM
21922 ." RC5toLCD is removed. type START to restart"
21923 COLD \ performs reset to reset all interrupt vectors.
21926 \ ------------------------------\
21927 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
21928 \ ------------------------------\
21929 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
21930 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21931 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21932 \ -- \ID input divider \ 10 = /4
21933 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21934 \ - \TBCLR TimerB Clear
21937 \ -------------------------------\
21938 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21939 \ -- \CM Capture Mode
21944 \ --- \OUTMOD \ 011 = set/reset
21950 \ -------------------------------\
21952 \ -------------------------------\
21954 \ ------------------------------\
21955 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21956 \ ------------------------------\
21957 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21958 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21959 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
21960 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21962 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
21963 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21965 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
21966 \ ------------------------------\
21967 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21968 \ ------------------------------\
21969 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
21970 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21971 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21972 \ ------------------------------\
21973 BIS.B #LCDVo,&LCDVo_DIR \
21974 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
21975 \ ------------------------------\
21976 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21977 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21978 \ ------------------------------\
21979 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21980 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21981 \ ******************************\
21983 \ ******************************\
21984 BIS.B #RC5,&IR_IE \ enable RC5_Int
21985 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21986 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21987 \ ******************************\
21988 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21989 \ ******************************\
21990 \ %01 0001 0100 \ TAxCTL
21991 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
21992 \ -- \ ID divided by 1
21993 \ -- \ MC MODE = up to TAxCCRn
21994 \ - \ TACLR clear timer count
21997 \ ------------------------------\
21998 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
21999 \ ------------------------------\
22001 \ --- \ TAIDEX pre divisor
22002 \ ------------------------------\
22003 \ %0000 0000 0000 0101 \ TAxCCR0
22004 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22005 \ ------------------------------\
22006 \ %0000 0000 0001 0000 \ TAxCCTL0
22007 \ - \ CAP capture/compare mode = compare
22010 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
22011 \ ------------------------------\
22012 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22013 \ ------------------------------\
22014 \ define LPM mode for ACCEPT \
22015 \ ------------------------------\
22016 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22017 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22018 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22019 \ ------------------------------\
22021 \ ------------------------------\
22022 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
22023 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22024 \ ------------------------------\
22025 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22026 \ ------------------------------\
22027 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
22028 \ CMP #2,Y \ Power_ON event
22029 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22031 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
22033 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22035 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22037 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22038 \ ------------------------------\
22040 \ ------------------------------\
22042 \ ------------------------------\
22043 #1000 20_US \ 1- wait 20 ms
22044 %011 TOP_LCD \ 2- send DB5=DB4=1
22045 #205 20_US \ 3- wait 4,1 ms
22046 %011 TOP_LCD \ 4- send again DB5=DB4=1
22047 #5 20_US \ 5- wait 0,1 ms
22048 %011 TOP_LCD \ 6- send again again DB5=DB4=1
22049 #2 20_US \ wait 40 us = LCD cycle
22050 %010 TOP_LCD \ 7- send DB5=1 DB4=0
22051 #2 20_US \ wait 40 us = LCD cycle
22052 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22053 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22054 LCD_CLEAR \ 10- "LCD_Clear"
22055 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22056 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22057 LCD_CLEAR \ 10- "LCD_Clear"
22058 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22059 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22060 CR ." I love you" \ display message on LCD
22061 ['] CR >BODY IS CR \ CR executes its default value
22062 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
22063 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22064 ABORT \ ...and end APP_INIT with ABORT, no return.
22067 \ ------------------------------\
22068 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
22069 \ ------------------------------\
22070 MOV #SLEEP,X \ replace default background process
22071 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
22072 MOV #WARM,X \ replace default WARM
22073 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
22074 MOV X,PC \ then execute it
22077 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
22081 CODE 20_US \ n -- n * 20 us
22082 BEGIN \ here we presume that LCD_TIM_IFG = 1...
22084 BIT #1,&LCD_TIM_CTL \ 3
22085 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
22086 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
22088 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
22093 CODE TOP_LCD \ LCD Sample
22094 \ \ if write : %xxxxWWWW --
22095 \ \ if read : -- %0000RRRR
22096 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22097 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22098 0= IF \ write LCD bits pattern
22099 AND.B #LCD_DB,TOS \
22100 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22101 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22104 THEN \ read LCD bits pattern
22107 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22108 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22109 AND.B #LCD_DB,TOS \
22113 CODE LCD_WRC \ char -- Write Char
22114 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22116 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22117 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22118 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22119 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22120 COLON \ high level word starts here
22121 TOP_LCD 2 20_US \ write high nibble first
22125 CODE LCD_WRF \ func -- Write Fonction
22126 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22130 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
22131 : LCD_HOME $02 LCD_WRF 100 20_us ;
22133 \ [UNDEFINED] OR [IF]
22135 \ \ https://forth-standard.org/standard/core/OR
22136 \ \ C OR x1 x2 -- x3 logical OR
22144 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
22145 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
22146 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
22147 \ : LCD_FN_SET $20 OR LCD_WrF ;
22148 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
22149 \ : LCD_GOTO $80 OR LCD_WrF ;
22152 \ CODE LCD_RDS \ -- status Read Status
22153 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22154 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22155 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22156 \ COLON \ starts a FORTH word
22157 \ TOP_LCD 2 20_us \ -- %0000HHHH
22158 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22159 \ HI2LO \ switch from FORTH to assembler
22160 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22161 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22162 \ MOV @RSP+,IP \ restore IP saved by COLON
22166 \ CODE LCD_RDC \ -- char Read Char
22167 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22172 \ ******************************\
22173 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22174 \ ******************************\
22175 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22176 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
22177 BIT.B #SW2,&SW2_IN \ test switch S2
22178 0= IF \ case of switch S2 pressed
22179 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22181 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
22184 BIT.B #SW1,&SW1_IN \ test switch S1 input
22185 0= IF \ case of Switch S1 pressed
22186 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
22188 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
22192 BW1 \ from quit on truncated RC5 message, repeated RC5 command
22196 \ ******************************\
22197 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22198 \ ******************************\
22199 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22200 \ ******************************\
22201 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22202 \ \ SMclock = 8|16|24 MHz
22203 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22204 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22205 \ \ SR(9)=new Toggle bit memory (ADD on)
22206 \ ******************************\
22207 \ RC5_FirstStartBitHalfCycle: \
22208 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22209 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22210 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
22211 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
22213 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
22214 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
22216 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
22217 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
22219 MOV #1778,X \ RC5_Period * 1us
22220 MOV #14,W \ count of loop
22222 \ ******************************\
22223 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
22224 \ ******************************\ |
22225 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22226 \ RC5_Compute_3/4_Period: \ |
22227 RRUM #1,X \ X=1/2 cycle |
22230 ADD X,Y \ Y=3/4 cycle
22231 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
22233 \ ******************************\
22234 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22235 \ ******************************\
22236 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22237 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
22238 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22239 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22240 SUB #1,W \ decrement count loop
22241 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
22242 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22243 0<> WHILE \ ----> out of loop ----+
22244 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22246 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
22247 CMP Y,X \ 1 | cycle time out of bound ?
22248 U>= IF \ 2 ^ | yes:
22249 BIC #$30,&RC5_TIM_CTL \ | | stop timer
22250 GOTO BW1 \ | | quit on truncated RC5 message
22252 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
22254 REPEAT \ ----> loop back --+ | with X = new RC5_period value
22255 \ ******************************\ |
22256 \ RC5_SampleEndOf: \ <---------------------+
22257 \ ******************************\
22258 BIC #$30,&RC5_TIM_CTL \ stop timer
22259 \ ******************************\
22260 \ RC5_ComputeNewRC5word \
22261 \ ******************************\
22262 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
22263 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
22264 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
22265 \ ******************************\
22266 \ RC5_ComputeC6bit \
22267 \ ******************************\
22268 BIT #BIT14,T \ test /C6 bit in T
22269 0= IF BIS #BIT6,X \ set C6 bit in X
22270 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
22271 \ ******************************\
22272 \ RC5_CommandByteIsDone \ -- BASE RC5_code
22273 \ ******************************\
22274 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22275 \ ******************************\
22276 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
22277 XOR @RSP,T \ (new XOR old) Toggle bits
22278 BIT #UF10,T \ repeated RC5_command ?
22279 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
22280 XOR #UF10,0(RSP) \ 5 toggle bit memory
22281 \ ******************************\
22282 \ Display IR_RC5 code \
22283 \ ******************************\
22284 SUB #8,PSP \ TOS -- x x x x TOS
22285 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
22286 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
22287 MOV #$10,&BASEADR \ set hexadecimal base
22288 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
22289 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
22290 LO2HI \ switch from assembler to FORTH
22291 LCD_CLEAR \ set LCD cursor at home
22292 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
22293 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
22294 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
22295 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
22296 HI2LO \ -- switch from FORTH to assembler
22297 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
22298 MOV @PSP+,TOS \ -- TOS
22302 \ ------------------------------\
22304 \ ------------------------------\
22306 \ ... \ insert here your background task
22309 CALL &RXON \ comment this line to disable TERMINAL
22311 \ ******************************\
22312 \ here start all interrupts \
22313 \ ******************************\
22314 \ here return all interrupts \
22315 \ ******************************\
22319 \ ------------------------------\
22320 CODE STOP \ stops multitasking, must to be used before downloading app
22321 \ ------------------------------\
22322 \ restore default action of primary DEFERred word SLEEP (assembly version)
22323 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
22324 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
22325 MOV X,-2(X) \ restore the default background
22326 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
22327 ['] WARM >BODY IS WARM \ restore the default WARM
22329 ." RC5toLCD is removed. type START to restart"
22330 COLD \ performs reset to reset all interrupt vectors.
22333 \ ------------------------------\
22334 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
22335 \ ------------------------------\
22336 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
22337 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22338 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22339 \ -- \ID input divider \ 10 = /4
22340 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22341 \ - \TBCLR TimerB Clear
22344 \ -------------------------------\
22345 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22346 \ -- \CM Capture Mode
22351 \ --- \OUTMOD \ 011 = set/reset
22357 \ -------------------------------\
22359 \ -------------------------------\
22361 \ ------------------------------\
22362 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22363 \ ------------------------------\
22364 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22365 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22366 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
22367 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22369 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
22370 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22372 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
22373 \ ------------------------------\
22374 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22375 \ ------------------------------\
22376 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
22377 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22378 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22379 \ ------------------------------\
22380 BIS.B #LCDVo,&LCDVo_DIR \
22381 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
22382 \ ------------------------------\
22383 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22384 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22385 \ ------------------------------\
22386 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22387 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22388 \ ******************************\
22390 \ ******************************\
22391 BIS.B #RC5,&IR_IE \ enable RC5_Int
22392 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22393 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22394 \ ******************************\
22395 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22396 \ ******************************\
22397 \ %01 0001 0100 \ TAxCTL
22398 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
22399 \ -- \ ID divided by 1
22400 \ -- \ MC MODE = up to TAxCCRn
22401 \ - \ TACLR clear timer count
22404 \ ------------------------------\
22405 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
22406 \ ------------------------------\
22408 \ --- \ TAIDEX pre divisor
22409 \ ------------------------------\
22410 \ %0000 0000 0000 0101 \ TAxCCR0
22411 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22412 \ ------------------------------\
22413 \ %0000 0000 0001 0000 \ TAxCCTL0
22414 \ - \ CAP capture/compare mode = compare
22417 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
22418 \ ------------------------------\
22419 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22420 \ ------------------------------\
22421 \ define LPM mode for ACCEPT \
22422 \ ------------------------------\
22423 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22424 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22425 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22426 \ ------------------------------\
22428 \ ------------------------------\
22429 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
22430 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22431 \ ------------------------------\
22432 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22433 \ ------------------------------\
22434 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
22435 \ CMP #2,Y \ Power_ON event
22436 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22438 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
22440 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22442 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22444 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22445 \ ------------------------------\
22447 \ ------------------------------\
22449 \ ------------------------------\
22450 #1000 20_US \ 1- wait 20 ms
22451 %011 TOP_LCD \ 2- send DB5=DB4=1
22452 #205 20_US \ 3- wait 4,1 ms
22453 %011 TOP_LCD \ 4- send again DB5=DB4=1
22454 #5 20_US \ 5- wait 0,1 ms
22455 %011 TOP_LCD \ 6- send again again DB5=DB4=1
22456 #2 20_US \ wait 40 us = LCD cycle
22457 %010 TOP_LCD \ 7- send DB5=1 DB4=0
22458 #2 20_US \ wait 40 us = LCD cycle
22459 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22460 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22461 LCD_CLEAR \ 10- "LCD_Clear"
22462 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22463 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22464 LCD_CLEAR \ 10- "LCD_Clear"
22465 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22466 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22467 CR ." I love you" \ display message on LCD
22468 ['] CR >BODY IS CR \ CR executes its default value
22469 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
22470 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22471 ABORT \ ...and end APP_INIT with ABORT, no return.
22474 \ ------------------------------\
22475 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
22476 \ ------------------------------\
22477 MOV #SLEEP,X \ replace default background process
22478 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
22479 MOV #WARM,X \ replace default WARM
22480 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
22481 MOV X,PC \ then execute it
22484 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
22488 CODE 20_US \ n -- n * 20 us
22489 BEGIN \ here we presume that LCD_TIM_IFG = 1...
22491 BIT #1,&LCD_TIM_CTL \ 3
22492 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
22493 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
22495 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
22500 CODE TOP_LCD \ LCD Sample
22501 \ \ if write : %xxxxWWWW --
22502 \ \ if read : -- %0000RRRR
22503 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22504 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22505 0= IF \ write LCD bits pattern
22506 AND.B #LCD_DB,TOS \
22507 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22508 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22511 THEN \ read LCD bits pattern
22514 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22515 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22516 AND.B #LCD_DB,TOS \
22520 CODE LCD_WRC \ char -- Write Char
22521 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22523 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22524 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22525 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22526 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22527 COLON \ high level word starts here
22528 TOP_LCD 2 20_US \ write high nibble first
22532 CODE LCD_WRF \ func -- Write Fonction
22533 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22537 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
22538 : LCD_HOME $02 LCD_WRF 100 20_us ;
22540 \ [UNDEFINED] OR [IF]
22542 \ \ https://forth-standard.org/standard/core/OR
22543 \ \ C OR x1 x2 -- x3 logical OR
22551 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
22552 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
22553 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
22554 \ : LCD_FN_SET $20 OR LCD_WrF ;
22555 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
22556 \ : LCD_GOTO $80 OR LCD_WrF ;
22559 \ CODE LCD_RDS \ -- status Read Status
22560 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22561 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22562 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22563 \ COLON \ starts a FORTH word
22564 \ TOP_LCD 2 20_us \ -- %0000HHHH
22565 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22566 \ HI2LO \ switch from FORTH to assembler
22567 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22568 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22569 \ MOV @RSP+,IP \ restore IP saved by COLON
22573 \ CODE LCD_RDC \ -- char Read Char
22574 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22579 \ ******************************\
22580 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22581 \ ******************************\
22582 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22583 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
22584 BIT.B #SW2,&SW2_IN \ test switch S2
22585 0= IF \ case of switch S2 pressed
22586 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22588 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
22591 BIT.B #SW1,&SW1_IN \ test switch S1 input
22592 0= IF \ case of Switch S1 pressed
22593 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
22595 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
22599 BW1 \ from quit on truncated RC5 message, repeated RC5 command
22603 \ ******************************\
22604 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22605 \ ******************************\
22606 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22607 \ ******************************\
22608 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22609 \ \ SMclock = 8|16|24 MHz
22610 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22611 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22612 \ \ SR(9)=new Toggle bit memory (ADD on)
22613 \ ******************************\
22614 \ RC5_FirstStartBitHalfCycle: \
22615 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22616 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22617 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
22618 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
22620 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
22621 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
22623 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
22624 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
22626 MOV #1778,X \ RC5_Period * 1us
22627 MOV #14,W \ count of loop
22629 \ ******************************\
22630 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
22631 \ ******************************\ |
22632 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22633 \ RC5_Compute_3/4_Period: \ |
22634 RRUM #1,X \ X=1/2 cycle |
22637 ADD X,Y \ Y=3/4 cycle
22638 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
22640 \ ******************************\
22641 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22642 \ ******************************\
22643 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22644 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
22645 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22646 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22647 SUB #1,W \ decrement count loop
22648 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
22649 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22650 0<> WHILE \ ----> out of loop ----+
22651 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22653 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
22654 CMP Y,X \ 1 | cycle time out of bound ?
22655 U>= IF \ 2 ^ | yes:
22656 BIC #$30,&RC5_TIM_CTL \ | | stop timer
22657 GOTO BW1 \ | | quit on truncated RC5 message
22659 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
22661 REPEAT \ ----> loop back --+ | with X = new RC5_period value
22662 \ ******************************\ |
22663 \ RC5_SampleEndOf: \ <---------------------+
22664 \ ******************************\
22665 BIC #$30,&RC5_TIM_CTL \ stop timer
22666 \ ******************************\
22667 \ RC5_ComputeNewRC5word \
22668 \ ******************************\
22669 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
22670 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
22671 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
22672 \ ******************************\
22673 \ RC5_ComputeC6bit \
22674 \ ******************************\
22675 BIT #BIT14,T \ test /C6 bit in T
22676 0= IF BIS #BIT6,X \ set C6 bit in X
22677 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
22678 \ ******************************\
22679 \ RC5_CommandByteIsDone \ -- BASE RC5_code
22680 \ ******************************\
22681 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22682 \ ******************************\
22683 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
22684 XOR @RSP,T \ (new XOR old) Toggle bits
22685 BIT #UF10,T \ repeated RC5_command ?
22686 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
22687 XOR #UF10,0(RSP) \ 5 toggle bit memory
22688 \ ******************************\
22689 \ Display IR_RC5 code \
22690 \ ******************************\
22691 SUB #8,PSP \ TOS -- x x x x TOS
22692 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
22693 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
22694 MOV #$10,&BASEADR \ set hexadecimal base
22695 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
22696 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
22697 LO2HI \ switch from assembler to FORTH
22698 LCD_CLEAR \ set LCD cursor at home
22699 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
22700 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
22701 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
22702 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
22703 HI2LO \ -- switch from FORTH to assembler
22704 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
22705 MOV @PSP+,TOS \ -- TOS
22709 \ ------------------------------\
22711 \ ------------------------------\
22713 \ ... \ insert here your background task
22716 CALL &RXON \ comment this line to disable TERMINAL
22718 \ ******************************\
22719 \ here start all interrupts \
22720 \ ******************************\
22721 \ here return all interrupts \
22722 \ ******************************\
22726 \ ------------------------------\
22727 CODE STOP \ stops multitasking, must to be used before downloading app
22728 \ ------------------------------\
22729 \ restore default action of primary DEFERred word SLEEP (assembly version)
22730 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
22731 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
22732 MOV X,-2(X) \ restore the default background
22733 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
22734 ['] WARM >BODY IS WARM \ restore the default WARM
22736 ." RC5toLCD is removed. type START to restart"
22737 COLD \ performs reset to reset all interrupt vectors.
22740 \ ------------------------------\
22741 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
22742 \ ------------------------------\
22743 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
22744 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22745 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22746 \ -- \ID input divider \ 10 = /4
22747 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22748 \ - \TBCLR TimerB Clear
22751 \ -------------------------------\
22752 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22753 \ -- \CM Capture Mode
22758 \ --- \OUTMOD \ 011 = set/reset
22764 \ -------------------------------\
22766 \ -------------------------------\
22768 \ ------------------------------\
22769 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22770 \ ------------------------------\
22771 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22772 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22773 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
22774 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22776 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
22777 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22779 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
22780 \ ------------------------------\
22781 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22782 \ ------------------------------\
22783 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
22784 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22785 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22786 \ ------------------------------\
22787 BIS.B #LCDVo,&LCDVo_DIR \
22788 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
22789 \ ------------------------------\
22790 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22791 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22792 \ ------------------------------\
22793 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22794 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22795 \ ******************************\
22797 \ ******************************\
22798 BIS.B #RC5,&IR_IE \ enable RC5_Int
22799 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22800 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22801 \ ******************************\
22802 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22803 \ ******************************\
22804 \ %01 0001 0100 \ TAxCTL
22805 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
22806 \ -- \ ID divided by 1
22807 \ -- \ MC MODE = up to TAxCCRn
22808 \ - \ TACLR clear timer count
22811 \ ------------------------------\
22812 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
22813 \ ------------------------------\
22815 \ --- \ TAIDEX pre divisor
22816 \ ------------------------------\
22817 \ %0000 0000 0000 0101 \ TAxCCR0
22818 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22819 \ ------------------------------\
22820 \ %0000 0000 0001 0000 \ TAxCCTL0
22821 \ - \ CAP capture/compare mode = compare
22824 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
22825 \ ------------------------------\
22826 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22827 \ ------------------------------\
22828 \ define LPM mode for ACCEPT \
22829 \ ------------------------------\
22830 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22831 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22832 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22833 \ ------------------------------\
22835 \ ------------------------------\
22836 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
22837 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22838 \ ------------------------------\
22839 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22840 \ ------------------------------\
22841 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
22842 \ CMP #2,Y \ Power_ON event
22843 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22845 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
22847 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22849 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22851 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22852 \ ------------------------------\
22854 \ ------------------------------\
22856 \ ------------------------------\
22857 #1000 20_US \ 1- wait 20 ms
22858 %011 TOP_LCD \ 2- send DB5=DB4=1
22859 #205 20_US \ 3- wait 4,1 ms
22860 %011 TOP_LCD \ 4- send again DB5=DB4=1
22861 #5 20_US \ 5- wait 0,1 ms
22862 %011 TOP_LCD \ 6- send again again DB5=DB4=1
22863 #2 20_US \ wait 40 us = LCD cycle
22864 %010 TOP_LCD \ 7- send DB5=1 DB4=0
22865 #2 20_US \ wait 40 us = LCD cycle
22866 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22867 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22868 LCD_CLEAR \ 10- "LCD_Clear"
22869 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22870 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22871 LCD_CLEAR \ 10- "LCD_Clear"
22872 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22873 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22874 CR ." I love you" \ display message on LCD
22875 ['] CR >BODY IS CR \ CR executes its default value
22876 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
22877 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22878 ABORT \ ...and end APP_INIT with ABORT, no return.
22881 \ ------------------------------\
22882 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
22883 \ ------------------------------\
22884 MOV #SLEEP,X \ replace default background process
22885 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
22886 MOV #WARM,X \ replace default WARM
22887 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
22888 MOV X,PC \ then execute it
22891 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
22895 CODE 20_US \ n -- n * 20 us
22896 BEGIN \ here we presume that LCD_TIM_IFG = 1...
22898 BIT #1,&LCD_TIM_CTL \ 3
22899 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
22900 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
22902 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
22907 CODE TOP_LCD \ LCD Sample
22908 \ \ if write : %xxxxWWWW --
22909 \ \ if read : -- %0000RRRR
22910 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22911 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22912 0= IF \ write LCD bits pattern
22913 AND.B #LCD_DB,TOS \
22914 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22915 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22918 THEN \ read LCD bits pattern
22921 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22922 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22923 AND.B #LCD_DB,TOS \
22927 CODE LCD_WRC \ char -- Write Char
22928 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22930 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22931 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22932 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22933 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22934 COLON \ high level word starts here
22935 TOP_LCD 2 20_US \ write high nibble first
22939 CODE LCD_WRF \ func -- Write Fonction
22940 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22944 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
22945 : LCD_HOME $02 LCD_WRF 100 20_us ;
22947 \ [UNDEFINED] OR [IF]
22949 \ \ https://forth-standard.org/standard/core/OR
22950 \ \ C OR x1 x2 -- x3 logical OR
22958 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
22959 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
22960 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
22961 \ : LCD_FN_SET $20 OR LCD_WrF ;
22962 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
22963 \ : LCD_GOTO $80 OR LCD_WrF ;
22966 \ CODE LCD_RDS \ -- status Read Status
22967 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22968 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22969 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22970 \ COLON \ starts a FORTH word
22971 \ TOP_LCD 2 20_us \ -- %0000HHHH
22972 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22973 \ HI2LO \ switch from FORTH to assembler
22974 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22975 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22976 \ MOV @RSP+,IP \ restore IP saved by COLON
22980 \ CODE LCD_RDC \ -- char Read Char
22981 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22986 \ ******************************\
22987 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22988 \ ******************************\
22989 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22990 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
22991 BIT.B #SW2,&SW2_IN \ test switch S2
22992 0= IF \ case of switch S2 pressed
22993 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22995 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
22998 BIT.B #SW1,&SW1_IN \ test switch S1 input
22999 0= IF \ case of Switch S1 pressed
23000 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23002 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23006 BW1 \ from quit on truncated RC5 message, repeated RC5 command
23010 \ ******************************\
23011 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23012 \ ******************************\
23013 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23014 \ ******************************\
23015 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23016 \ \ SMclock = 8|16|24 MHz
23017 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23018 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23019 \ \ SR(9)=new Toggle bit memory (ADD on)
23020 \ ******************************\
23021 \ RC5_FirstStartBitHalfCycle: \
23022 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23023 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23024 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23025 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23027 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23028 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23030 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23031 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23033 MOV #1778,X \ RC5_Period * 1us
23034 MOV #14,W \ count of loop
23036 \ ******************************\
23037 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23038 \ ******************************\ |
23039 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23040 \ RC5_Compute_3/4_Period: \ |
23041 RRUM #1,X \ X=1/2 cycle |
23044 ADD X,Y \ Y=3/4 cycle
23045 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23047 \ ******************************\
23048 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23049 \ ******************************\
23050 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23051 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23052 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23053 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23054 SUB #1,W \ decrement count loop
23055 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23056 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23057 0<> WHILE \ ----> out of loop ----+
23058 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23060 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23061 CMP Y,X \ 1 | cycle time out of bound ?
23062 U>= IF \ 2 ^ | yes:
23063 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23064 GOTO BW1 \ | | quit on truncated RC5 message
23066 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23068 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23069 \ ******************************\ |
23070 \ RC5_SampleEndOf: \ <---------------------+
23071 \ ******************************\
23072 BIC #$30,&RC5_TIM_CTL \ stop timer
23073 \ ******************************\
23074 \ RC5_ComputeNewRC5word \
23075 \ ******************************\
23076 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23077 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23078 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23079 \ ******************************\
23080 \ RC5_ComputeC6bit \
23081 \ ******************************\
23082 BIT #BIT14,T \ test /C6 bit in T
23083 0= IF BIS #BIT6,X \ set C6 bit in X
23084 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23085 \ ******************************\
23086 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23087 \ ******************************\
23088 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23089 \ ******************************\
23090 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23091 XOR @RSP,T \ (new XOR old) Toggle bits
23092 BIT #UF10,T \ repeated RC5_command ?
23093 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
23094 XOR #UF10,0(RSP) \ 5 toggle bit memory
23095 \ ******************************\
23096 \ Display IR_RC5 code \
23097 \ ******************************\
23098 SUB #8,PSP \ TOS -- x x x x TOS
23099 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23100 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23101 MOV #$10,&BASEADR \ set hexadecimal base
23102 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23103 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23104 LO2HI \ switch from assembler to FORTH
23105 LCD_CLEAR \ set LCD cursor at home
23106 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23107 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23108 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23109 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23110 HI2LO \ -- switch from FORTH to assembler
23111 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23112 MOV @PSP+,TOS \ -- TOS
23116 \ ------------------------------\
23118 \ ------------------------------\
23120 \ ... \ insert here your background task
23123 CALL &RXON \ comment this line to disable TERMINAL
23125 \ ******************************\
23126 \ here start all interrupts \
23127 \ ******************************\
23128 \ here return all interrupts \
23129 \ ******************************\
23133 \ ------------------------------\
23134 CODE STOP \ stops multitasking, must to be used before downloading app
23135 \ ------------------------------\
23136 \ restore default action of primary DEFERred word SLEEP (assembly version)
23137 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
23138 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23139 MOV X,-2(X) \ restore the default background
23140 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23141 ['] WARM >BODY IS WARM \ restore the default WARM
23143 ." RC5toLCD is removed. type START to restart"
23144 COLD \ performs reset to reset all interrupt vectors.
23147 \ ------------------------------\
23148 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
23149 \ ------------------------------\
23150 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
23151 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23152 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23153 \ -- \ID input divider \ 10 = /4
23154 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
23155 \ - \TBCLR TimerB Clear
23158 \ -------------------------------\
23159 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23160 \ -- \CM Capture Mode
23165 \ --- \OUTMOD \ 011 = set/reset
23171 \ -------------------------------\
23173 \ -------------------------------\
23175 \ ------------------------------\
23176 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
23177 \ ------------------------------\
23178 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
23179 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
23180 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
23181 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
23183 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
23184 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
23186 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
23187 \ ------------------------------\
23188 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
23189 \ ------------------------------\
23190 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
23191 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
23192 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23193 \ ------------------------------\
23194 BIS.B #LCDVo,&LCDVo_DIR \
23195 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
23196 \ ------------------------------\
23197 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23198 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23199 \ ------------------------------\
23200 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23201 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23202 \ ******************************\
23204 \ ******************************\
23205 BIS.B #RC5,&IR_IE \ enable RC5_Int
23206 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23207 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23208 \ ******************************\
23209 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
23210 \ ******************************\
23211 \ %01 0001 0100 \ TAxCTL
23212 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
23213 \ -- \ ID divided by 1
23214 \ -- \ MC MODE = up to TAxCCRn
23215 \ - \ TACLR clear timer count
23218 \ ------------------------------\
23219 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
23220 \ ------------------------------\
23222 \ --- \ TAIDEX pre divisor
23223 \ ------------------------------\
23224 \ %0000 0000 0000 0101 \ TAxCCR0
23225 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
23226 \ ------------------------------\
23227 \ %0000 0000 0001 0000 \ TAxCCTL0
23228 \ - \ CAP capture/compare mode = compare
23231 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
23232 \ ------------------------------\
23233 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
23234 \ ------------------------------\
23235 \ define LPM mode for ACCEPT \
23236 \ ------------------------------\
23237 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23238 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23239 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23240 \ ------------------------------\
23242 \ ------------------------------\
23243 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
23244 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
23245 \ ------------------------------\
23246 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
23247 \ ------------------------------\
23248 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
23249 \ CMP #2,Y \ Power_ON event
23250 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
23252 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
23254 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
23256 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
23258 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
23259 \ ------------------------------\
23261 \ ------------------------------\
23263 \ ------------------------------\
23264 #1000 20_US \ 1- wait 20 ms
23265 %011 TOP_LCD \ 2- send DB5=DB4=1
23266 #205 20_US \ 3- wait 4,1 ms
23267 %011 TOP_LCD \ 4- send again DB5=DB4=1
23268 #5 20_US \ 5- wait 0,1 ms
23269 %011 TOP_LCD \ 6- send again again DB5=DB4=1
23270 #2 20_US \ wait 40 us = LCD cycle
23271 %010 TOP_LCD \ 7- send DB5=1 DB4=0
23272 #2 20_US \ wait 40 us = LCD cycle
23273 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23274 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23275 LCD_CLEAR \ 10- "LCD_Clear"
23276 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23277 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23278 LCD_CLEAR \ 10- "LCD_Clear"
23279 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23280 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23281 CR ." I love you" \ display message on LCD
23282 ['] CR >BODY IS CR \ CR executes its default value
23283 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
23284 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
23285 ABORT \ ...and end APP_INIT with ABORT, no return.
23288 \ ------------------------------\
23289 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
23290 \ ------------------------------\
23291 MOV #SLEEP,X \ replace default background process
23292 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
23293 MOV #WARM,X \ replace default WARM
23294 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
23295 MOV X,PC \ then execute it
23298 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
23302 CODE 20_US \ n -- n * 20 us
23303 BEGIN \ here we presume that LCD_TIM_IFG = 1...
23305 BIT #1,&LCD_TIM_CTL \ 3
23306 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
23307 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
23309 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
23314 CODE TOP_LCD \ LCD Sample
23315 \ \ if write : %xxxxWWWW --
23316 \ \ if read : -- %0000RRRR
23317 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23318 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23319 0= IF \ write LCD bits pattern
23320 AND.B #LCD_DB,TOS \
23321 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23322 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23325 THEN \ read LCD bits pattern
23328 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23329 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23330 AND.B #LCD_DB,TOS \
23334 CODE LCD_WRC \ char -- Write Char
23335 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23337 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23338 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23339 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23340 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23341 COLON \ high level word starts here
23342 TOP_LCD 2 20_US \ write high nibble first
23346 CODE LCD_WRF \ func -- Write Fonction
23347 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23351 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
23352 : LCD_HOME $02 LCD_WRF 100 20_us ;
23354 \ [UNDEFINED] OR [IF]
23356 \ \ https://forth-standard.org/standard/core/OR
23357 \ \ C OR x1 x2 -- x3 logical OR
23365 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
23366 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
23367 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
23368 \ : LCD_FN_SET $20 OR LCD_WrF ;
23369 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
23370 \ : LCD_GOTO $80 OR LCD_WrF ;
23373 \ CODE LCD_RDS \ -- status Read Status
23374 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23375 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23376 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23377 \ COLON \ starts a FORTH word
23378 \ TOP_LCD 2 20_us \ -- %0000HHHH
23379 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23380 \ HI2LO \ switch from FORTH to assembler
23381 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23382 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23383 \ MOV @RSP+,IP \ restore IP saved by COLON
23387 \ CODE LCD_RDC \ -- char Read Char
23388 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23393 \ ******************************\
23394 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23395 \ ******************************\
23396 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23397 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
23398 BIT.B #SW2,&SW2_IN \ test switch S2
23399 0= IF \ case of switch S2 pressed
23400 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23402 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
23405 BIT.B #SW1,&SW1_IN \ test switch S1 input
23406 0= IF \ case of Switch S1 pressed
23407 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23409 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23413 BW1 \ from quit on truncated RC5 message, repeated RC5 command
23417 \ ******************************\
23418 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23419 \ ******************************\
23420 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23421 \ ******************************\
23422 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23423 \ \ SMclock = 8|16|24 MHz
23424 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23425 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23426 \ \ SR(9)=new Toggle bit memory (ADD on)
23427 \ ******************************\
23428 \ RC5_FirstStartBitHalfCycle: \
23429 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23430 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23431 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23432 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23434 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23435 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23437 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23438 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23440 MOV #1778,X \ RC5_Period * 1us
23441 MOV #14,W \ count of loop
23443 \ ******************************\
23444 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23445 \ ******************************\ |
23446 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23447 \ RC5_Compute_3/4_Period: \ |
23448 RRUM #1,X \ X=1/2 cycle |
23451 ADD X,Y \ Y=3/4 cycle
23452 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23454 \ ******************************\
23455 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23456 \ ******************************\
23457 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23458 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23459 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23460 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23461 SUB #1,W \ decrement count loop
23462 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23463 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23464 0<> WHILE \ ----> out of loop ----+
23465 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23467 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23468 CMP Y,X \ 1 | cycle time out of bound ?
23469 U>= IF \ 2 ^ | yes:
23470 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23471 GOTO BW1 \ | | quit on truncated RC5 message
23473 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23475 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23476 \ ******************************\ |
23477 \ RC5_SampleEndOf: \ <---------------------+
23478 \ ******************************\
23479 BIC #$30,&RC5_TIM_CTL \ stop timer
23480 \ ******************************\
23481 \ RC5_ComputeNewRC5word \
23482 \ ******************************\
23483 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23484 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23485 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23486 \ ******************************\
23487 \ RC5_ComputeC6bit \
23488 \ ******************************\
23489 BIT #BIT14,T \ test /C6 bit in T
23490 0= IF BIS #BIT6,X \ set C6 bit in X
23491 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23492 \ ******************************\
23493 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23494 \ ******************************\
23495 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23496 \ ******************************\
23497 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23498 XOR @RSP,T \ (new XOR old) Toggle bits
23499 BIT #UF10,T \ repeated RC5_command ?
23500 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
23501 XOR #UF10,0(RSP) \ 5 toggle bit memory
23502 \ ******************************\
23503 \ Display IR_RC5 code \
23504 \ ******************************\
23505 SUB #8,PSP \ TOS -- x x x x TOS
23506 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23507 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23508 MOV #$10,&BASEADR \ set hexadecimal base
23509 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23510 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23511 LO2HI \ switch from assembler to FORTH
23512 LCD_CLEAR \ set LCD cursor at home
23513 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23514 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23515 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23516 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23517 HI2LO \ -- switch from FORTH to assembler
23518 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23519 MOV @PSP+,TOS \ -- TOS
23523 \ ------------------------------\
23525 \ ------------------------------\
23527 \ ... \ insert here your background task
23530 CALL &RXON \ comment this line to disable TERMINAL
23532 \ ******************************\
23533 \ here start all interrupts \
23534 \ ******************************\
23535 \ here return all interrupts \
23536 \ ******************************\
23540 \ ------------------------------\
23541 CODE STOP \ stops multitasking, must to be used before downloading app
23542 \ ------------------------------\
23543 \ restore default action of primary DEFERred word SLEEP (assembly version)
23544 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
23545 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23546 MOV X,-2(X) \ restore the default background
23547 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23548 ['] WARM >BODY IS WARM \ restore the default WARM
23550 ." RC5toLCD is removed. type START to restart"
23551 COLD \ performs reset to reset all interrupt vectors.
23554 \ ------------------------------\
23555 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
23556 \ ------------------------------\
23557 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
23558 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23559 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23560 \ -- \ID input divider \ 10 = /4
23561 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
23562 \ - \TBCLR TimerB Clear
23565 \ -------------------------------\
23566 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23567 \ -- \CM Capture Mode
23572 \ --- \OUTMOD \ 011 = set/reset
23578 \ -------------------------------\
23580 \ -------------------------------\
23582 \ ------------------------------\
23583 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
23584 \ ------------------------------\
23585 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
23586 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
23587 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
23588 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
23590 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
23591 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
23593 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
23594 \ ------------------------------\
23595 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
23596 \ ------------------------------\
23597 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
23598 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
23599 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23600 \ ------------------------------\
23601 BIS.B #LCDVo,&LCDVo_DIR \
23602 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
23603 \ ------------------------------\
23604 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23605 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23606 \ ------------------------------\
23607 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23608 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23609 \ ******************************\
23611 \ ******************************\
23612 BIS.B #RC5,&IR_IE \ enable RC5_Int
23613 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23614 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23615 \ ******************************\
23616 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
23617 \ ******************************\
23618 \ %01 0001 0100 \ TAxCTL
23619 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
23620 \ -- \ ID divided by 1
23621 \ -- \ MC MODE = up to TAxCCRn
23622 \ - \ TACLR clear timer count
23625 \ ------------------------------\
23626 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
23627 \ ------------------------------\
23629 \ --- \ TAIDEX pre divisor
23630 \ ------------------------------\
23631 \ %0000 0000 0000 0101 \ TAxCCR0
23632 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
23633 \ ------------------------------\
23634 \ %0000 0000 0001 0000 \ TAxCCTL0
23635 \ - \ CAP capture/compare mode = compare
23638 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
23639 \ ------------------------------\
23640 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
23641 \ ------------------------------\
23642 \ define LPM mode for ACCEPT \
23643 \ ------------------------------\
23644 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23645 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23646 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23647 \ ------------------------------\
23649 \ ------------------------------\
23650 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
23651 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
23652 \ ------------------------------\
23653 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
23654 \ ------------------------------\
23655 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
23656 \ CMP #2,Y \ Power_ON event
23657 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
23659 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
23661 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
23663 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
23665 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
23666 \ ------------------------------\
23668 \ ------------------------------\
23670 \ ------------------------------\
23671 #1000 20_US \ 1- wait 20 ms
23672 %011 TOP_LCD \ 2- send DB5=DB4=1
23673 #205 20_US \ 3- wait 4,1 ms
23674 %011 TOP_LCD \ 4- send again DB5=DB4=1
23675 #5 20_US \ 5- wait 0,1 ms
23676 %011 TOP_LCD \ 6- send again again DB5=DB4=1
23677 #2 20_US \ wait 40 us = LCD cycle
23678 %010 TOP_LCD \ 7- send DB5=1 DB4=0
23679 #2 20_US \ wait 40 us = LCD cycle
23680 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23681 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23682 LCD_CLEAR \ 10- "LCD_Clear"
23683 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23684 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23685 LCD_CLEAR \ 10- "LCD_Clear"
23686 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23687 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23688 CR ." I love you" \ display message on LCD
23689 ['] CR >BODY IS CR \ CR executes its default value
23690 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
23691 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
23692 ABORT \ ...and end APP_INIT with ABORT, no return.
23695 \ ------------------------------\
23696 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
23697 \ ------------------------------\
23698 MOV #SLEEP,X \ replace default background process
23699 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
23700 MOV #WARM,X \ replace default WARM
23701 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
23702 MOV X,PC \ then execute it
23705 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
23709 CODE 20_US \ n -- n * 20 us
23710 BEGIN \ here we presume that LCD_TIM_IFG = 1...
23712 BIT #1,&LCD_TIM_CTL \ 3
23713 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
23714 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
23716 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
23721 CODE TOP_LCD \ LCD Sample
23722 \ \ if write : %xxxxWWWW --
23723 \ \ if read : -- %0000RRRR
23724 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23725 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23726 0= IF \ write LCD bits pattern
23727 AND.B #LCD_DB,TOS \
23728 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23729 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23732 THEN \ read LCD bits pattern
23735 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23736 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23737 AND.B #LCD_DB,TOS \
23741 CODE LCD_WRC \ char -- Write Char
23742 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23744 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23745 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23746 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23747 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23748 COLON \ high level word starts here
23749 TOP_LCD 2 20_US \ write high nibble first
23753 CODE LCD_WRF \ func -- Write Fonction
23754 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23758 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
23759 : LCD_HOME $02 LCD_WRF 100 20_us ;
23761 \ [UNDEFINED] OR [IF]
23763 \ \ https://forth-standard.org/standard/core/OR
23764 \ \ C OR x1 x2 -- x3 logical OR
23772 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
23773 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
23774 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
23775 \ : LCD_FN_SET $20 OR LCD_WrF ;
23776 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
23777 \ : LCD_GOTO $80 OR LCD_WrF ;
23780 \ CODE LCD_RDS \ -- status Read Status
23781 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23782 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23783 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23784 \ COLON \ starts a FORTH word
23785 \ TOP_LCD 2 20_us \ -- %0000HHHH
23786 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23787 \ HI2LO \ switch from FORTH to assembler
23788 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23789 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23790 \ MOV @RSP+,IP \ restore IP saved by COLON
23794 \ CODE LCD_RDC \ -- char Read Char
23795 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23800 \ ******************************\
23801 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23802 \ ******************************\
23803 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23804 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
23805 BIT.B #SW2,&SW2_IN \ test switch S2
23806 0= IF \ case of switch S2 pressed
23807 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23809 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
23812 BIT.B #SW1,&SW1_IN \ test switch S1 input
23813 0= IF \ case of Switch S1 pressed
23814 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23816 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23820 BW1 \ from quit on truncated RC5 message, repeated RC5 command
23824 \ ******************************\
23825 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23826 \ ******************************\
23827 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23828 \ ******************************\
23829 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23830 \ \ SMclock = 8|16|24 MHz
23831 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23832 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23833 \ \ SR(9)=new Toggle bit memory (ADD on)
23834 \ ******************************\
23835 \ RC5_FirstStartBitHalfCycle: \
23836 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23837 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23838 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23839 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23841 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23842 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23844 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23845 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23847 MOV #1778,X \ RC5_Period * 1us
23848 MOV #14,W \ count of loop
23850 \ ******************************\
23851 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23852 \ ******************************\ |
23853 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23854 \ RC5_Compute_3/4_Period: \ |
23855 RRUM #1,X \ X=1/2 cycle |
23858 ADD X,Y \ Y=3/4 cycle
23859 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23861 \ ******************************\
23862 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23863 \ ******************************\
23864 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23865 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23866 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23867 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23868 SUB #1,W \ decrement count loop
23869 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23870 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23871 0<> WHILE \ ----> out of loop ----+
23872 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23874 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23875 CMP Y,X \ 1 | cycle time out of bound ?
23876 U>= IF \ 2 ^ | yes:
23877 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23878 GOTO BW1 \ | | quit on truncated RC5 message
23880 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23882 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23883 \ ******************************\ |
23884 \ RC5_SampleEndOf: \ <---------------------+
23885 \ ******************************\
23886 BIC #$30,&RC5_TIM_CTL \ stop timer
23887 \ ******************************\
23888 \ RC5_ComputeNewRC5word \
23889 \ ******************************\
23890 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23891 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23892 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23893 \ ******************************\
23894 \ RC5_ComputeC6bit \
23895 \ ******************************\
23896 BIT #BIT14,T \ test /C6 bit in T
23897 0= IF BIS #BIT6,X \ set C6 bit in X
23898 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23899 \ ******************************\
23900 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23901 \ ******************************\
23902 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23903 \ ******************************\
23904 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23905 XOR @RSP,T \ (new XOR old) Toggle bits
23906 BIT #UF10,T \ repeated RC5_command ?
23907 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
23908 XOR #UF10,0(RSP) \ 5 toggle bit memory
23909 \ ******************************\
23910 \ Display IR_RC5 code \
23911 \ ******************************\
23912 SUB #8,PSP \ TOS -- x x x x TOS
23913 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23914 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23915 MOV #$10,&BASEADR \ set hexadecimal base
23916 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23917 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23918 LO2HI \ switch from assembler to FORTH
23919 LCD_CLEAR \ set LCD cursor at home
23920 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23921 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23922 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23923 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23924 HI2LO \ -- switch from FORTH to assembler
23925 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23926 MOV @PSP+,TOS \ -- TOS
23930 \ ------------------------------\
23932 \ ------------------------------\
23934 \ ... \ insert here your background task
23937 CALL &RXON \ comment this line to disable TERMINAL
23939 \ ******************************\
23940 \ here start all interrupts \
23941 \ ******************************\
23942 \ here return all interrupts \
23943 \ ******************************\
23947 \ ------------------------------\
23948 CODE STOP \ stops multitasking, must to be used before downloading app
23949 \ ------------------------------\
23950 \ restore default action of primary DEFERred word SLEEP (assembly version)
23951 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
23952 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23953 MOV X,-2(X) \ restore the default background
23954 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23955 ['] WARM >BODY IS WARM \ restore the default WARM
23957 ." RC5toLCD is removed. type START to restart"
23958 COLD \ performs reset to reset all interrupt vectors.
23961 \ ------------------------------\
23962 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
23963 \ ------------------------------\
23964 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
23965 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23966 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23967 \ -- \ID input divider \ 10 = /4
23968 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
23969 \ - \TBCLR TimerB Clear
23972 \ -------------------------------\
23973 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23974 \ -- \CM Capture Mode
23979 \ --- \OUTMOD \ 011 = set/reset
23985 \ -------------------------------\
23987 \ -------------------------------\
23989 \ ------------------------------\
23990 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
23991 \ ------------------------------\
23992 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
23993 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
23994 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
23995 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
23997 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
23998 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24000 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24001 \ ------------------------------\
24002 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24003 \ ------------------------------\
24004 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24005 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24006 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24007 \ ------------------------------\
24008 BIS.B #LCDVo,&LCDVo_DIR \
24009 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24010 \ ------------------------------\
24011 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24012 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24013 \ ------------------------------\
24014 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24015 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24016 \ ******************************\
24018 \ ******************************\
24019 BIS.B #RC5,&IR_IE \ enable RC5_Int
24020 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24021 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24022 \ ******************************\
24023 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24024 \ ******************************\
24025 \ %01 0001 0100 \ TAxCTL
24026 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24027 \ -- \ ID divided by 1
24028 \ -- \ MC MODE = up to TAxCCRn
24029 \ - \ TACLR clear timer count
24032 \ ------------------------------\
24033 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24034 \ ------------------------------\
24036 \ --- \ TAIDEX pre divisor
24037 \ ------------------------------\
24038 \ %0000 0000 0000 0101 \ TAxCCR0
24039 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24040 \ ------------------------------\
24041 \ %0000 0000 0001 0000 \ TAxCCTL0
24042 \ - \ CAP capture/compare mode = compare
24045 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24046 \ ------------------------------\
24047 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24048 \ ------------------------------\
24049 \ define LPM mode for ACCEPT \
24050 \ ------------------------------\
24051 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24052 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24053 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24054 \ ------------------------------\
24056 \ ------------------------------\
24057 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
24058 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24059 \ ------------------------------\
24060 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24061 \ ------------------------------\
24062 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
24063 \ CMP #2,Y \ Power_ON event
24064 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24066 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
24068 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24070 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24072 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24073 \ ------------------------------\
24075 \ ------------------------------\
24077 \ ------------------------------\
24078 #1000 20_US \ 1- wait 20 ms
24079 %011 TOP_LCD \ 2- send DB5=DB4=1
24080 #205 20_US \ 3- wait 4,1 ms
24081 %011 TOP_LCD \ 4- send again DB5=DB4=1
24082 #5 20_US \ 5- wait 0,1 ms
24083 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24084 #2 20_US \ wait 40 us = LCD cycle
24085 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24086 #2 20_US \ wait 40 us = LCD cycle
24087 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24088 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24089 LCD_CLEAR \ 10- "LCD_Clear"
24090 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24091 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24092 LCD_CLEAR \ 10- "LCD_Clear"
24093 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24094 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24095 CR ." I love you" \ display message on LCD
24096 ['] CR >BODY IS CR \ CR executes its default value
24097 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24098 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24099 ABORT \ ...and end APP_INIT with ABORT, no return.
24102 \ ------------------------------\
24103 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
24104 \ ------------------------------\
24105 MOV #SLEEP,X \ replace default background process
24106 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
24107 MOV #WARM,X \ replace default WARM
24108 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
24109 MOV X,PC \ then execute it
24112 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24116 CODE 20_US \ n -- n * 20 us
24117 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24119 BIT #1,&LCD_TIM_CTL \ 3
24120 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24121 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24123 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24128 CODE TOP_LCD \ LCD Sample
24129 \ \ if write : %xxxxWWWW --
24130 \ \ if read : -- %0000RRRR
24131 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24132 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24133 0= IF \ write LCD bits pattern
24134 AND.B #LCD_DB,TOS \
24135 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24136 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24139 THEN \ read LCD bits pattern
24142 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24143 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24144 AND.B #LCD_DB,TOS \
24148 CODE LCD_WRC \ char -- Write Char
24149 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24151 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24152 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24153 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24154 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24155 COLON \ high level word starts here
24156 TOP_LCD 2 20_US \ write high nibble first
24160 CODE LCD_WRF \ func -- Write Fonction
24161 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24165 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
24166 : LCD_HOME $02 LCD_WRF 100 20_us ;
24168 \ [UNDEFINED] OR [IF]
24170 \ \ https://forth-standard.org/standard/core/OR
24171 \ \ C OR x1 x2 -- x3 logical OR
24179 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
24180 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
24181 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
24182 \ : LCD_FN_SET $20 OR LCD_WrF ;
24183 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
24184 \ : LCD_GOTO $80 OR LCD_WrF ;
24187 \ CODE LCD_RDS \ -- status Read Status
24188 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24189 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24190 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24191 \ COLON \ starts a FORTH word
24192 \ TOP_LCD 2 20_us \ -- %0000HHHH
24193 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
24194 \ HI2LO \ switch from FORTH to assembler
24195 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
24196 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
24197 \ MOV @RSP+,IP \ restore IP saved by COLON
24201 \ CODE LCD_RDC \ -- char Read Char
24202 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24207 \ ******************************\
24208 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24209 \ ******************************\
24210 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
24211 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
24212 BIT.B #SW2,&SW2_IN \ test switch S2
24213 0= IF \ case of switch S2 pressed
24214 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
24216 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
24219 BIT.B #SW1,&SW1_IN \ test switch S1 input
24220 0= IF \ case of Switch S1 pressed
24221 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
24223 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
24227 BW1 \ from quit on truncated RC5 message, repeated RC5 command
24231 \ ******************************\
24232 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24233 \ ******************************\
24234 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24235 \ ******************************\
24236 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24237 \ \ SMclock = 8|16|24 MHz
24238 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
24239 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
24240 \ \ SR(9)=new Toggle bit memory (ADD on)
24241 \ ******************************\
24242 \ RC5_FirstStartBitHalfCycle: \
24243 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
24244 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
24245 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
24246 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
24248 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
24249 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
24251 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
24252 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
24254 MOV #1778,X \ RC5_Period * 1us
24255 MOV #14,W \ count of loop
24257 \ ******************************\
24258 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
24259 \ ******************************\ |
24260 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
24261 \ RC5_Compute_3/4_Period: \ |
24262 RRUM #1,X \ X=1/2 cycle |
24265 ADD X,Y \ Y=3/4 cycle
24266 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
24268 \ ******************************\
24269 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
24270 \ ******************************\
24271 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24272 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
24273 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24274 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24275 SUB #1,W \ decrement count loop
24276 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
24277 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24278 0<> WHILE \ ----> out of loop ----+
24279 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
24281 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
24282 CMP Y,X \ 1 | cycle time out of bound ?
24283 U>= IF \ 2 ^ | yes:
24284 BIC #$30,&RC5_TIM_CTL \ | | stop timer
24285 GOTO BW1 \ | | quit on truncated RC5 message
24287 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
24289 REPEAT \ ----> loop back --+ | with X = new RC5_period value
24290 \ ******************************\ |
24291 \ RC5_SampleEndOf: \ <---------------------+
24292 \ ******************************\
24293 BIC #$30,&RC5_TIM_CTL \ stop timer
24294 \ ******************************\
24295 \ RC5_ComputeNewRC5word \
24296 \ ******************************\
24297 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
24298 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
24299 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
24300 \ ******************************\
24301 \ RC5_ComputeC6bit \
24302 \ ******************************\
24303 BIT #BIT14,T \ test /C6 bit in T
24304 0= IF BIS #BIT6,X \ set C6 bit in X
24305 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
24306 \ ******************************\
24307 \ RC5_CommandByteIsDone \ -- BASE RC5_code
24308 \ ******************************\
24309 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24310 \ ******************************\
24311 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
24312 XOR @RSP,T \ (new XOR old) Toggle bits
24313 BIT #UF10,T \ repeated RC5_command ?
24314 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
24315 XOR #UF10,0(RSP) \ 5 toggle bit memory
24316 \ ******************************\
24317 \ Display IR_RC5 code \
24318 \ ******************************\
24319 SUB #8,PSP \ TOS -- x x x x TOS
24320 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
24321 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
24322 MOV #$10,&BASEADR \ set hexadecimal base
24323 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
24324 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
24325 LO2HI \ switch from assembler to FORTH
24326 LCD_CLEAR \ set LCD cursor at home
24327 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
24328 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
24329 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
24330 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
24331 HI2LO \ -- switch from FORTH to assembler
24332 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
24333 MOV @PSP+,TOS \ -- TOS
24337 \ ------------------------------\
24339 \ ------------------------------\
24341 \ ... \ insert here your background task
24344 CALL &RXON \ comment this line to disable TERMINAL
24346 \ ******************************\
24347 \ here start all interrupts \
24348 \ ******************************\
24349 \ here return all interrupts \
24350 \ ******************************\
24354 \ ------------------------------\
24355 CODE STOP \ stops multitasking, must to be used before downloading app
24356 \ ------------------------------\
24357 \ restore default action of primary DEFERred word SLEEP (assembly version)
24358 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
24359 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
24360 MOV X,-2(X) \ restore the default background
24361 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
24362 ['] WARM >BODY IS WARM \ restore the default WARM
24364 ." RC5toLCD is removed. type START to restart"
24365 COLD \ performs reset to reset all interrupt vectors.
24368 \ ------------------------------\
24369 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
24370 \ ------------------------------\
24371 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
24372 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24373 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24374 \ -- \ID input divider \ 10 = /4
24375 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24376 \ - \TBCLR TimerB Clear
24379 \ -------------------------------\
24380 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24381 \ -- \CM Capture Mode
24386 \ --- \OUTMOD \ 011 = set/reset
24392 \ -------------------------------\
24394 \ -------------------------------\
24396 \ ------------------------------\
24397 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24398 \ ------------------------------\
24399 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24400 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24401 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
24402 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24404 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
24405 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24407 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24408 \ ------------------------------\
24409 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24410 \ ------------------------------\
24411 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24412 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24413 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24414 \ ------------------------------\
24415 BIS.B #LCDVo,&LCDVo_DIR \
24416 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24417 \ ------------------------------\
24418 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24419 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24420 \ ------------------------------\
24421 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24422 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24423 \ ******************************\
24425 \ ******************************\
24426 BIS.B #RC5,&IR_IE \ enable RC5_Int
24427 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24428 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24429 \ ******************************\
24430 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24431 \ ******************************\
24432 \ %01 0001 0100 \ TAxCTL
24433 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24434 \ -- \ ID divided by 1
24435 \ -- \ MC MODE = up to TAxCCRn
24436 \ - \ TACLR clear timer count
24439 \ ------------------------------\
24440 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24441 \ ------------------------------\
24443 \ --- \ TAIDEX pre divisor
24444 \ ------------------------------\
24445 \ %0000 0000 0000 0101 \ TAxCCR0
24446 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24447 \ ------------------------------\
24448 \ %0000 0000 0001 0000 \ TAxCCTL0
24449 \ - \ CAP capture/compare mode = compare
24452 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24453 \ ------------------------------\
24454 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24455 \ ------------------------------\
24456 \ define LPM mode for ACCEPT \
24457 \ ------------------------------\
24458 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24459 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24460 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24461 \ ------------------------------\
24463 \ ------------------------------\
24464 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
24465 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24466 \ ------------------------------\
24467 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24468 \ ------------------------------\
24469 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
24470 \ CMP #2,Y \ Power_ON event
24471 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24473 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
24475 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24477 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24479 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24480 \ ------------------------------\
24482 \ ------------------------------\
24484 \ ------------------------------\
24485 #1000 20_US \ 1- wait 20 ms
24486 %011 TOP_LCD \ 2- send DB5=DB4=1
24487 #205 20_US \ 3- wait 4,1 ms
24488 %011 TOP_LCD \ 4- send again DB5=DB4=1
24489 #5 20_US \ 5- wait 0,1 ms
24490 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24491 #2 20_US \ wait 40 us = LCD cycle
24492 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24493 #2 20_US \ wait 40 us = LCD cycle
24494 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24495 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24496 LCD_CLEAR \ 10- "LCD_Clear"
24497 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24498 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24499 LCD_CLEAR \ 10- "LCD_Clear"
24500 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24501 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24502 CR ." I love you" \ display message on LCD
24503 ['] CR >BODY IS CR \ CR executes its default value
24504 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24505 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24506 ABORT \ ...and end APP_INIT with ABORT, no return.
24509 \ ------------------------------\
24510 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
24511 \ ------------------------------\
24512 MOV #SLEEP,X \ replace default background process
24513 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
24514 MOV #WARM,X \ replace default WARM
24515 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
24516 MOV X,PC \ then execute it
24519 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24523 CODE 20_US \ n -- n * 20 us
24524 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24526 BIT #1,&LCD_TIM_CTL \ 3
24527 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24528 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24530 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24535 CODE TOP_LCD \ LCD Sample
24536 \ \ if write : %xxxxWWWW --
24537 \ \ if read : -- %0000RRRR
24538 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24539 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24540 0= IF \ write LCD bits pattern
24541 AND.B #LCD_DB,TOS \
24542 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24543 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24546 THEN \ read LCD bits pattern
24549 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24550 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24551 AND.B #LCD_DB,TOS \
24555 CODE LCD_WRC \ char -- Write Char
24556 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24558 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24559 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24560 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24561 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24562 COLON \ high level word starts here
24563 TOP_LCD 2 20_US \ write high nibble first
24567 CODE LCD_WRF \ func -- Write Fonction
24568 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24572 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
24573 : LCD_HOME $02 LCD_WRF 100 20_us ;
24575 \ [UNDEFINED] OR [IF]
24577 \ \ https://forth-standard.org/standard/core/OR
24578 \ \ C OR x1 x2 -- x3 logical OR
24586 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
24587 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
24588 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
24589 \ : LCD_FN_SET $20 OR LCD_WrF ;
24590 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
24591 \ : LCD_GOTO $80 OR LCD_WrF ;
24594 \ CODE LCD_RDS \ -- status Read Status
24595 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24596 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24597 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24598 \ COLON \ starts a FORTH word
24599 \ TOP_LCD 2 20_us \ -- %0000HHHH
24600 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
24601 \ HI2LO \ switch from FORTH to assembler
24602 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
24603 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
24604 \ MOV @RSP+,IP \ restore IP saved by COLON
24608 \ CODE LCD_RDC \ -- char Read Char
24609 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24614 \ ******************************\
24615 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24616 \ ******************************\
24617 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
24618 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
24619 BIT.B #SW2,&SW2_IN \ test switch S2
24620 0= IF \ case of switch S2 pressed
24621 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
24623 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
24626 BIT.B #SW1,&SW1_IN \ test switch S1 input
24627 0= IF \ case of Switch S1 pressed
24628 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
24630 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
24634 BW1 \ from quit on truncated RC5 message, repeated RC5 command
24638 \ ******************************\
24639 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24640 \ ******************************\
24641 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24642 \ ******************************\
24643 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24644 \ \ SMclock = 8|16|24 MHz
24645 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
24646 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
24647 \ \ SR(9)=new Toggle bit memory (ADD on)
24648 \ ******************************\
24649 \ RC5_FirstStartBitHalfCycle: \
24650 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
24651 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
24652 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
24653 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
24655 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
24656 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
24658 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
24659 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
24661 MOV #1778,X \ RC5_Period * 1us
24662 MOV #14,W \ count of loop
24664 \ ******************************\
24665 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
24666 \ ******************************\ |
24667 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
24668 \ RC5_Compute_3/4_Period: \ |
24669 RRUM #1,X \ X=1/2 cycle |
24672 ADD X,Y \ Y=3/4 cycle
24673 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
24675 \ ******************************\
24676 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
24677 \ ******************************\
24678 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24679 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
24680 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24681 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24682 SUB #1,W \ decrement count loop
24683 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
24684 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24685 0<> WHILE \ ----> out of loop ----+
24686 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
24688 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
24689 CMP Y,X \ 1 | cycle time out of bound ?
24690 U>= IF \ 2 ^ | yes:
24691 BIC #$30,&RC5_TIM_CTL \ | | stop timer
24692 GOTO BW1 \ | | quit on truncated RC5 message
24694 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
24696 REPEAT \ ----> loop back --+ | with X = new RC5_period value
24697 \ ******************************\ |
24698 \ RC5_SampleEndOf: \ <---------------------+
24699 \ ******************************\
24700 BIC #$30,&RC5_TIM_CTL \ stop timer
24701 \ ******************************\
24702 \ RC5_ComputeNewRC5word \
24703 \ ******************************\
24704 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
24705 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
24706 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
24707 \ ******************************\
24708 \ RC5_ComputeC6bit \
24709 \ ******************************\
24710 BIT #BIT14,T \ test /C6 bit in T
24711 0= IF BIS #BIT6,X \ set C6 bit in X
24712 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
24713 \ ******************************\
24714 \ RC5_CommandByteIsDone \ -- BASE RC5_code
24715 \ ******************************\
24716 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24717 \ ******************************\
24718 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
24719 XOR @RSP,T \ (new XOR old) Toggle bits
24720 BIT #UF10,T \ repeated RC5_command ?
24721 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
24722 XOR #UF10,0(RSP) \ 5 toggle bit memory
24723 \ ******************************\
24724 \ Display IR_RC5 code \
24725 \ ******************************\
24726 SUB #8,PSP \ TOS -- x x x x TOS
24727 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
24728 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
24729 MOV #$10,&BASEADR \ set hexadecimal base
24730 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
24731 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
24732 LO2HI \ switch from assembler to FORTH
24733 LCD_CLEAR \ set LCD cursor at home
24734 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
24735 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
24736 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
24737 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
24738 HI2LO \ -- switch from FORTH to assembler
24739 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
24740 MOV @PSP+,TOS \ -- TOS
24744 \ ------------------------------\
24746 \ ------------------------------\
24748 \ ... \ insert here your background task
24751 CALL &RXON \ comment this line to disable TERMINAL
24753 \ ******************************\
24754 \ here start all interrupts \
24755 \ ******************************\
24756 \ here return all interrupts \
24757 \ ******************************\
24761 \ ------------------------------\
24762 CODE STOP \ stops multitasking, must to be used before downloading app
24763 \ ------------------------------\
24764 \ restore default action of primary DEFERred word SLEEP (assembly version)
24765 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
24766 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
24767 MOV X,-2(X) \ restore the default background
24768 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
24769 ['] WARM >BODY IS WARM \ restore the default WARM
24771 ." RC5toLCD is removed. type START to restart"
24772 COLD \ performs reset to reset all interrupt vectors.
24775 \ ------------------------------\
24776 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
24777 \ ------------------------------\
24778 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
24779 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24780 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24781 \ -- \ID input divider \ 10 = /4
24782 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24783 \ - \TBCLR TimerB Clear
24786 \ -------------------------------\
24787 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24788 \ -- \CM Capture Mode
24793 \ --- \OUTMOD \ 011 = set/reset
24799 \ -------------------------------\
24801 \ -------------------------------\
24803 \ ------------------------------\
24804 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24805 \ ------------------------------\
24806 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24807 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24808 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
24809 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24811 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
24812 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24814 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24815 \ ------------------------------\
24816 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24817 \ ------------------------------\
24818 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24819 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24820 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24821 \ ------------------------------\
24822 BIS.B #LCDVo,&LCDVo_DIR \
24823 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24824 \ ------------------------------\
24825 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24826 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24827 \ ------------------------------\
24828 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24829 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24830 \ ******************************\
24832 \ ******************************\
24833 BIS.B #RC5,&IR_IE \ enable RC5_Int
24834 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24835 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24836 \ ******************************\
24837 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24838 \ ******************************\
24839 \ %01 0001 0100 \ TAxCTL
24840 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24841 \ -- \ ID divided by 1
24842 \ -- \ MC MODE = up to TAxCCRn
24843 \ - \ TACLR clear timer count
24846 \ ------------------------------\
24847 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24848 \ ------------------------------\
24850 \ --- \ TAIDEX pre divisor
24851 \ ------------------------------\
24852 \ %0000 0000 0000 0101 \ TAxCCR0
24853 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24854 \ ------------------------------\
24855 \ %0000 0000 0001 0000 \ TAxCCTL0
24856 \ - \ CAP capture/compare mode = compare
24859 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24860 \ ------------------------------\
24861 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24862 \ ------------------------------\
24863 \ define LPM mode for ACCEPT \
24864 \ ------------------------------\
24865 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24866 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24867 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24868 \ ------------------------------\
24870 \ ------------------------------\
24871 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
24872 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24873 \ ------------------------------\
24874 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24875 \ ------------------------------\
24876 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
24877 \ CMP #2,Y \ Power_ON event
24878 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24880 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
24882 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24884 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24886 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24887 \ ------------------------------\
24889 \ ------------------------------\
24891 \ ------------------------------\
24892 #1000 20_US \ 1- wait 20 ms
24893 %011 TOP_LCD \ 2- send DB5=DB4=1
24894 #205 20_US \ 3- wait 4,1 ms
24895 %011 TOP_LCD \ 4- send again DB5=DB4=1
24896 #5 20_US \ 5- wait 0,1 ms
24897 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24898 #2 20_US \ wait 40 us = LCD cycle
24899 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24900 #2 20_US \ wait 40 us = LCD cycle
24901 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24902 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24903 LCD_CLEAR \ 10- "LCD_Clear"
24904 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24905 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24906 LCD_CLEAR \ 10- "LCD_Clear"
24907 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24908 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24909 CR ." I love you" \ display message on LCD
24910 ['] CR >BODY IS CR \ CR executes its default value
24911 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24912 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24913 ABORT \ ...and end APP_INIT with ABORT, no return.
24916 \ ------------------------------\
24917 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
24918 \ ------------------------------\
24919 MOV #SLEEP,X \ replace default background process
24920 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
24921 MOV #WARM,X \ replace default WARM
24922 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
24923 MOV X,PC \ then execute it
24926 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24930 CODE 20_US \ n -- n * 20 us
24931 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24933 BIT #1,&LCD_TIM_CTL \ 3
24934 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24935 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24937 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24942 CODE TOP_LCD \ LCD Sample
24943 \ \ if write : %xxxxWWWW --
24944 \ \ if read : -- %0000RRRR
24945 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24946 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24947 0= IF \ write LCD bits pattern
24948 AND.B #LCD_DB,TOS \
24949 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24950 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24953 THEN \ read LCD bits pattern
24956 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24957 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24958 AND.B #LCD_DB,TOS \
24962 CODE LCD_WRC \ char -- Write Char
24963 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24965 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24966 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24967 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24968 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24969 COLON \ high level word starts here
24970 TOP_LCD 2 20_US \ write high nibble first
24974 CODE LCD_WRF \ func -- Write Fonction
24975 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24979 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
24980 : LCD_HOME $02 LCD_WRF 100 20_us ;
24982 \ [UNDEFINED] OR [IF]
24984 \ \ https://forth-standard.org/standard/core/OR
24985 \ \ C OR x1 x2 -- x3 logical OR
24993 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
24994 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
24995 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
24996 \ : LCD_FN_SET $20 OR LCD_WrF ;
24997 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
24998 \ : LCD_GOTO $80 OR LCD_WrF ;
25001 \ CODE LCD_RDS \ -- status Read Status
25002 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25003 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25004 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25005 \ COLON \ starts a FORTH word
25006 \ TOP_LCD 2 20_us \ -- %0000HHHH
25007 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25008 \ HI2LO \ switch from FORTH to assembler
25009 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25010 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25011 \ MOV @RSP+,IP \ restore IP saved by COLON
25015 \ CODE LCD_RDC \ -- char Read Char
25016 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25021 \ ******************************\
25022 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25023 \ ******************************\
25024 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25025 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
25026 BIT.B #SW2,&SW2_IN \ test switch S2
25027 0= IF \ case of switch S2 pressed
25028 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25030 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
25033 BIT.B #SW1,&SW1_IN \ test switch S1 input
25034 0= IF \ case of Switch S1 pressed
25035 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25037 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25041 BW1 \ from quit on truncated RC5 message, repeated RC5 command
25045 \ ******************************\
25046 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25047 \ ******************************\
25048 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25049 \ ******************************\
25050 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25051 \ \ SMclock = 8|16|24 MHz
25052 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25053 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25054 \ \ SR(9)=new Toggle bit memory (ADD on)
25055 \ ******************************\
25056 \ RC5_FirstStartBitHalfCycle: \
25057 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25058 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25059 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
25060 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
25062 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
25063 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
25065 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
25066 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
25068 MOV #1778,X \ RC5_Period * 1us
25069 MOV #14,W \ count of loop
25071 \ ******************************\
25072 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
25073 \ ******************************\ |
25074 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25075 \ RC5_Compute_3/4_Period: \ |
25076 RRUM #1,X \ X=1/2 cycle |
25079 ADD X,Y \ Y=3/4 cycle
25080 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
25082 \ ******************************\
25083 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25084 \ ******************************\
25085 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25086 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
25087 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25088 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25089 SUB #1,W \ decrement count loop
25090 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
25091 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25092 0<> WHILE \ ----> out of loop ----+
25093 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25095 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25096 CMP Y,X \ 1 | cycle time out of bound ?
25097 U>= IF \ 2 ^ | yes:
25098 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25099 GOTO BW1 \ | | quit on truncated RC5 message
25101 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25103 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25104 \ ******************************\ |
25105 \ RC5_SampleEndOf: \ <---------------------+
25106 \ ******************************\
25107 BIC #$30,&RC5_TIM_CTL \ stop timer
25108 \ ******************************\
25109 \ RC5_ComputeNewRC5word \
25110 \ ******************************\
25111 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25112 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25113 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25114 \ ******************************\
25115 \ RC5_ComputeC6bit \
25116 \ ******************************\
25117 BIT #BIT14,T \ test /C6 bit in T
25118 0= IF BIS #BIT6,X \ set C6 bit in X
25119 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25120 \ ******************************\
25121 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25122 \ ******************************\
25123 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25124 \ ******************************\
25125 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25126 XOR @RSP,T \ (new XOR old) Toggle bits
25127 BIT #UF10,T \ repeated RC5_command ?
25128 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
25129 XOR #UF10,0(RSP) \ 5 toggle bit memory
25130 \ ******************************\
25131 \ Display IR_RC5 code \
25132 \ ******************************\
25133 SUB #8,PSP \ TOS -- x x x x TOS
25134 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25135 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25136 MOV #$10,&BASEADR \ set hexadecimal base
25137 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25138 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25139 LO2HI \ switch from assembler to FORTH
25140 LCD_CLEAR \ set LCD cursor at home
25141 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25142 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25143 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25144 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25145 HI2LO \ -- switch from FORTH to assembler
25146 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25147 MOV @PSP+,TOS \ -- TOS
25151 \ ------------------------------\
25153 \ ------------------------------\
25155 \ ... \ insert here your background task
25158 CALL &RXON \ comment this line to disable TERMINAL
25160 \ ******************************\
25161 \ here start all interrupts \
25162 \ ******************************\
25163 \ here return all interrupts \
25164 \ ******************************\
25168 \ ------------------------------\
25169 CODE STOP \ stops multitasking, must to be used before downloading app
25170 \ ------------------------------\
25171 \ restore default action of primary DEFERred word SLEEP (assembly version)
25172 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
25173 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25174 MOV X,-2(X) \ restore the default background
25175 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25176 ['] WARM >BODY IS WARM \ restore the default WARM
25178 ." RC5toLCD is removed. type START to restart"
25179 COLD \ performs reset to reset all interrupt vectors.
25182 \ ------------------------------\
25183 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
25184 \ ------------------------------\
25185 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
25186 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25187 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25188 \ -- \ID input divider \ 10 = /4
25189 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25190 \ - \TBCLR TimerB Clear
25193 \ -------------------------------\
25194 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25195 \ -- \CM Capture Mode
25200 \ --- \OUTMOD \ 011 = set/reset
25206 \ -------------------------------\
25208 \ -------------------------------\
25210 \ ------------------------------\
25211 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25212 \ ------------------------------\
25213 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25214 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25215 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
25216 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25218 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
25219 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25221 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
25222 \ ------------------------------\
25223 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25224 \ ------------------------------\
25225 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
25226 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25227 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25228 \ ------------------------------\
25229 BIS.B #LCDVo,&LCDVo_DIR \
25230 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
25231 \ ------------------------------\
25232 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25233 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25234 \ ------------------------------\
25235 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25236 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25237 \ ******************************\
25239 \ ******************************\
25240 BIS.B #RC5,&IR_IE \ enable RC5_Int
25241 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25242 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25243 \ ******************************\
25244 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25245 \ ******************************\
25246 \ %01 0001 0100 \ TAxCTL
25247 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
25248 \ -- \ ID divided by 1
25249 \ -- \ MC MODE = up to TAxCCRn
25250 \ - \ TACLR clear timer count
25253 \ ------------------------------\
25254 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
25255 \ ------------------------------\
25257 \ --- \ TAIDEX pre divisor
25258 \ ------------------------------\
25259 \ %0000 0000 0000 0101 \ TAxCCR0
25260 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25261 \ ------------------------------\
25262 \ %0000 0000 0001 0000 \ TAxCCTL0
25263 \ - \ CAP capture/compare mode = compare
25266 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
25267 \ ------------------------------\
25268 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25269 \ ------------------------------\
25270 \ define LPM mode for ACCEPT \
25271 \ ------------------------------\
25272 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25273 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25274 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25275 \ ------------------------------\
25277 \ ------------------------------\
25278 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
25279 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
25280 \ ------------------------------\
25281 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
25282 \ ------------------------------\
25283 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
25284 \ CMP #2,Y \ Power_ON event
25285 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
25287 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
25289 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
25291 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
25293 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
25294 \ ------------------------------\
25296 \ ------------------------------\
25298 \ ------------------------------\
25299 #1000 20_US \ 1- wait 20 ms
25300 %011 TOP_LCD \ 2- send DB5=DB4=1
25301 #205 20_US \ 3- wait 4,1 ms
25302 %011 TOP_LCD \ 4- send again DB5=DB4=1
25303 #5 20_US \ 5- wait 0,1 ms
25304 %011 TOP_LCD \ 6- send again again DB5=DB4=1
25305 #2 20_US \ wait 40 us = LCD cycle
25306 %010 TOP_LCD \ 7- send DB5=1 DB4=0
25307 #2 20_US \ wait 40 us = LCD cycle
25308 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25309 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25310 LCD_CLEAR \ 10- "LCD_Clear"
25311 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25312 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25313 LCD_CLEAR \ 10- "LCD_Clear"
25314 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25315 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25316 CR ." I love you" \ display message on LCD
25317 ['] CR >BODY IS CR \ CR executes its default value
25318 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
25319 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25320 ABORT \ ...and end APP_INIT with ABORT, no return.
25323 \ ------------------------------\
25324 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
25325 \ ------------------------------\
25326 MOV #SLEEP,X \ replace default background process
25327 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
25328 MOV #WARM,X \ replace default WARM
25329 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
25330 MOV X,PC \ then execute it
25333 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
25337 CODE 20_US \ n -- n * 20 us
25338 BEGIN \ here we presume that LCD_TIM_IFG = 1...
25340 BIT #1,&LCD_TIM_CTL \ 3
25341 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
25342 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
25344 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
25349 CODE TOP_LCD \ LCD Sample
25350 \ \ if write : %xxxxWWWW --
25351 \ \ if read : -- %0000RRRR
25352 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25353 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25354 0= IF \ write LCD bits pattern
25355 AND.B #LCD_DB,TOS \
25356 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25357 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25360 THEN \ read LCD bits pattern
25363 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25364 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25365 AND.B #LCD_DB,TOS \
25369 CODE LCD_WRC \ char -- Write Char
25370 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25372 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
25373 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
25374 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25375 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25376 COLON \ high level word starts here
25377 TOP_LCD 2 20_US \ write high nibble first
25381 CODE LCD_WRF \ func -- Write Fonction
25382 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25386 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
25387 : LCD_HOME $02 LCD_WRF 100 20_us ;
25389 \ [UNDEFINED] OR [IF]
25391 \ \ https://forth-standard.org/standard/core/OR
25392 \ \ C OR x1 x2 -- x3 logical OR
25400 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
25401 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
25402 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
25403 \ : LCD_FN_SET $20 OR LCD_WrF ;
25404 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
25405 \ : LCD_GOTO $80 OR LCD_WrF ;
25408 \ CODE LCD_RDS \ -- status Read Status
25409 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25410 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25411 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25412 \ COLON \ starts a FORTH word
25413 \ TOP_LCD 2 20_us \ -- %0000HHHH
25414 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25415 \ HI2LO \ switch from FORTH to assembler
25416 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25417 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25418 \ MOV @RSP+,IP \ restore IP saved by COLON
25422 \ CODE LCD_RDC \ -- char Read Char
25423 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25428 \ ******************************\
25429 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25430 \ ******************************\
25431 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25432 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
25433 BIT.B #SW2,&SW2_IN \ test switch S2
25434 0= IF \ case of switch S2 pressed
25435 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25437 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
25440 BIT.B #SW1,&SW1_IN \ test switch S1 input
25441 0= IF \ case of Switch S1 pressed
25442 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25444 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25448 BW1 \ from quit on truncated RC5 message, repeated RC5 command
25452 \ ******************************\
25453 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25454 \ ******************************\
25455 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25456 \ ******************************\
25457 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25458 \ \ SMclock = 8|16|24 MHz
25459 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25460 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25461 \ \ SR(9)=new Toggle bit memory (ADD on)
25462 \ ******************************\
25463 \ RC5_FirstStartBitHalfCycle: \
25464 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25465 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25466 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
25467 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
25469 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
25470 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
25472 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
25473 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
25475 MOV #1778,X \ RC5_Period * 1us
25476 MOV #14,W \ count of loop
25478 \ ******************************\
25479 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
25480 \ ******************************\ |
25481 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25482 \ RC5_Compute_3/4_Period: \ |
25483 RRUM #1,X \ X=1/2 cycle |
25486 ADD X,Y \ Y=3/4 cycle
25487 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
25489 \ ******************************\
25490 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25491 \ ******************************\
25492 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25493 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
25494 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25495 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25496 SUB #1,W \ decrement count loop
25497 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
25498 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25499 0<> WHILE \ ----> out of loop ----+
25500 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25502 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25503 CMP Y,X \ 1 | cycle time out of bound ?
25504 U>= IF \ 2 ^ | yes:
25505 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25506 GOTO BW1 \ | | quit on truncated RC5 message
25508 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25510 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25511 \ ******************************\ |
25512 \ RC5_SampleEndOf: \ <---------------------+
25513 \ ******************************\
25514 BIC #$30,&RC5_TIM_CTL \ stop timer
25515 \ ******************************\
25516 \ RC5_ComputeNewRC5word \
25517 \ ******************************\
25518 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25519 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25520 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25521 \ ******************************\
25522 \ RC5_ComputeC6bit \
25523 \ ******************************\
25524 BIT #BIT14,T \ test /C6 bit in T
25525 0= IF BIS #BIT6,X \ set C6 bit in X
25526 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25527 \ ******************************\
25528 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25529 \ ******************************\
25530 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25531 \ ******************************\
25532 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25533 XOR @RSP,T \ (new XOR old) Toggle bits
25534 BIT #UF10,T \ repeated RC5_command ?
25535 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
25536 XOR #UF10,0(RSP) \ 5 toggle bit memory
25537 \ ******************************\
25538 \ Display IR_RC5 code \
25539 \ ******************************\
25540 SUB #8,PSP \ TOS -- x x x x TOS
25541 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25542 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25543 MOV #$10,&BASEADR \ set hexadecimal base
25544 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25545 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25546 LO2HI \ switch from assembler to FORTH
25547 LCD_CLEAR \ set LCD cursor at home
25548 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25549 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25550 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25551 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25552 HI2LO \ -- switch from FORTH to assembler
25553 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25554 MOV @PSP+,TOS \ -- TOS
25558 \ ------------------------------\
25560 \ ------------------------------\
25562 \ ... \ insert here your background task
25565 CALL &RXON \ comment this line to disable TERMINAL
25567 \ ******************************\
25568 \ here start all interrupts \
25569 \ ******************************\
25570 \ here return all interrupts \
25571 \ ******************************\
25575 \ ------------------------------\
25576 CODE STOP \ stops multitasking, must to be used before downloading app
25577 \ ------------------------------\
25578 \ restore default action of primary DEFERred word SLEEP (assembly version)
25579 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
25580 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25581 MOV X,-2(X) \ restore the default background
25582 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25583 ['] WARM >BODY IS WARM \ restore the default WARM
25585 ." RC5toLCD is removed. type START to restart"
25586 COLD \ performs reset to reset all interrupt vectors.
25589 \ ------------------------------\
25590 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
25591 \ ------------------------------\
25592 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
25593 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25594 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25595 \ -- \ID input divider \ 10 = /4
25596 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25597 \ - \TBCLR TimerB Clear
25600 \ -------------------------------\
25601 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25602 \ -- \CM Capture Mode
25607 \ --- \OUTMOD \ 011 = set/reset
25613 \ -------------------------------\
25615 \ -------------------------------\
25617 \ ------------------------------\
25618 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25619 \ ------------------------------\
25620 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25621 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25622 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
25623 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25625 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
25626 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25628 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
25629 \ ------------------------------\
25630 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25631 \ ------------------------------\
25632 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
25633 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25634 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25635 \ ------------------------------\
25636 BIS.B #LCDVo,&LCDVo_DIR \
25637 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
25638 \ ------------------------------\
25639 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25640 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25641 \ ------------------------------\
25642 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25643 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25644 \ ******************************\
25646 \ ******************************\
25647 BIS.B #RC5,&IR_IE \ enable RC5_Int
25648 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25649 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25650 \ ******************************\
25651 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25652 \ ******************************\
25653 \ %01 0001 0100 \ TAxCTL
25654 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
25655 \ -- \ ID divided by 1
25656 \ -- \ MC MODE = up to TAxCCRn
25657 \ - \ TACLR clear timer count
25660 \ ------------------------------\
25661 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
25662 \ ------------------------------\
25664 \ --- \ TAIDEX pre divisor
25665 \ ------------------------------\
25666 \ %0000 0000 0000 0101 \ TAxCCR0
25667 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25668 \ ------------------------------\
25669 \ %0000 0000 0001 0000 \ TAxCCTL0
25670 \ - \ CAP capture/compare mode = compare
25673 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
25674 \ ------------------------------\
25675 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25676 \ ------------------------------\
25677 \ define LPM mode for ACCEPT \
25678 \ ------------------------------\
25679 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25680 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25681 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25682 \ ------------------------------\
25684 \ ------------------------------\
25685 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
25686 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
25687 \ ------------------------------\
25688 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
25689 \ ------------------------------\
25690 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
25691 \ CMP #2,Y \ Power_ON event
25692 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
25694 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
25696 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
25698 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
25700 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
25701 \ ------------------------------\
25703 \ ------------------------------\
25705 \ ------------------------------\
25706 #1000 20_US \ 1- wait 20 ms
25707 %011 TOP_LCD \ 2- send DB5=DB4=1
25708 #205 20_US \ 3- wait 4,1 ms
25709 %011 TOP_LCD \ 4- send again DB5=DB4=1
25710 #5 20_US \ 5- wait 0,1 ms
25711 %011 TOP_LCD \ 6- send again again DB5=DB4=1
25712 #2 20_US \ wait 40 us = LCD cycle
25713 %010 TOP_LCD \ 7- send DB5=1 DB4=0
25714 #2 20_US \ wait 40 us = LCD cycle
25715 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25716 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25717 LCD_CLEAR \ 10- "LCD_Clear"
25718 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25719 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25720 LCD_CLEAR \ 10- "LCD_Clear"
25721 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25722 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25723 CR ." I love you" \ display message on LCD
25724 ['] CR >BODY IS CR \ CR executes its default value
25725 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
25726 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25727 ABORT \ ...and end APP_INIT with ABORT, no return.
25730 \ ------------------------------\
25731 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
25732 \ ------------------------------\
25733 MOV #SLEEP,X \ replace default background process
25734 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
25735 MOV #WARM,X \ replace default WARM
25736 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
25737 MOV X,PC \ then execute it
25740 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
25744 CODE 20_US \ n -- n * 20 us
25745 BEGIN \ here we presume that LCD_TIM_IFG = 1...
25747 BIT #1,&LCD_TIM_CTL \ 3
25748 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
25749 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
25751 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
25756 CODE TOP_LCD \ LCD Sample
25757 \ \ if write : %xxxxWWWW --
25758 \ \ if read : -- %0000RRRR
25759 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25760 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25761 0= IF \ write LCD bits pattern
25762 AND.B #LCD_DB,TOS \
25763 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25764 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25767 THEN \ read LCD bits pattern
25770 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25771 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25772 AND.B #LCD_DB,TOS \
25776 CODE LCD_WRC \ char -- Write Char
25777 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25779 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
25780 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
25781 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25782 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25783 COLON \ high level word starts here
25784 TOP_LCD 2 20_US \ write high nibble first
25788 CODE LCD_WRF \ func -- Write Fonction
25789 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25793 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
25794 : LCD_HOME $02 LCD_WRF 100 20_us ;
25796 \ [UNDEFINED] OR [IF]
25798 \ \ https://forth-standard.org/standard/core/OR
25799 \ \ C OR x1 x2 -- x3 logical OR
25807 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
25808 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
25809 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
25810 \ : LCD_FN_SET $20 OR LCD_WrF ;
25811 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
25812 \ : LCD_GOTO $80 OR LCD_WrF ;
25815 \ CODE LCD_RDS \ -- status Read Status
25816 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25817 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25818 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25819 \ COLON \ starts a FORTH word
25820 \ TOP_LCD 2 20_us \ -- %0000HHHH
25821 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25822 \ HI2LO \ switch from FORTH to assembler
25823 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25824 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25825 \ MOV @RSP+,IP \ restore IP saved by COLON
25829 \ CODE LCD_RDC \ -- char Read Char
25830 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25835 \ ******************************\
25836 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25837 \ ******************************\
25838 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25839 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
25840 BIT.B #SW2,&SW2_IN \ test switch S2
25841 0= IF \ case of switch S2 pressed
25842 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25844 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
25847 BIT.B #SW1,&SW1_IN \ test switch S1 input
25848 0= IF \ case of Switch S1 pressed
25849 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25851 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25855 BW1 \ from quit on truncated RC5 message, repeated RC5 command
25859 \ ******************************\
25860 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25861 \ ******************************\
25862 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25863 \ ******************************\
25864 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25865 \ \ SMclock = 8|16|24 MHz
25866 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25867 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25868 \ \ SR(9)=new Toggle bit memory (ADD on)
25869 \ ******************************\
25870 \ RC5_FirstStartBitHalfCycle: \
25871 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25872 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25873 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
25874 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
25876 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
25877 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
25879 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
25880 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
25882 MOV #1778,X \ RC5_Period * 1us
25883 MOV #14,W \ count of loop
25885 \ ******************************\
25886 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
25887 \ ******************************\ |
25888 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25889 \ RC5_Compute_3/4_Period: \ |
25890 RRUM #1,X \ X=1/2 cycle |
25893 ADD X,Y \ Y=3/4 cycle
25894 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
25896 \ ******************************\
25897 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25898 \ ******************************\
25899 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25900 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
25901 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25902 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25903 SUB #1,W \ decrement count loop
25904 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
25905 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25906 0<> WHILE \ ----> out of loop ----+
25907 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25909 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25910 CMP Y,X \ 1 | cycle time out of bound ?
25911 U>= IF \ 2 ^ | yes:
25912 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25913 GOTO BW1 \ | | quit on truncated RC5 message
25915 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25917 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25918 \ ******************************\ |
25919 \ RC5_SampleEndOf: \ <---------------------+
25920 \ ******************************\
25921 BIC #$30,&RC5_TIM_CTL \ stop timer
25922 \ ******************************\
25923 \ RC5_ComputeNewRC5word \
25924 \ ******************************\
25925 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25926 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25927 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25928 \ ******************************\
25929 \ RC5_ComputeC6bit \
25930 \ ******************************\
25931 BIT #BIT14,T \ test /C6 bit in T
25932 0= IF BIS #BIT6,X \ set C6 bit in X
25933 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25934 \ ******************************\
25935 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25936 \ ******************************\
25937 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25938 \ ******************************\
25939 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25940 XOR @RSP,T \ (new XOR old) Toggle bits
25941 BIT #UF10,T \ repeated RC5_command ?
25942 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
25943 XOR #UF10,0(RSP) \ 5 toggle bit memory
25944 \ ******************************\
25945 \ Display IR_RC5 code \
25946 \ ******************************\
25947 SUB #8,PSP \ TOS -- x x x x TOS
25948 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25949 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25950 MOV #$10,&BASEADR \ set hexadecimal base
25951 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25952 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25953 LO2HI \ switch from assembler to FORTH
25954 LCD_CLEAR \ set LCD cursor at home
25955 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25956 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25957 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25958 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25959 HI2LO \ -- switch from FORTH to assembler
25960 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25961 MOV @PSP+,TOS \ -- TOS
25965 \ ------------------------------\
25967 \ ------------------------------\
25969 \ ... \ insert here your background task
25972 CALL &RXON \ comment this line to disable TERMINAL
25974 \ ******************************\
25975 \ here start all interrupts \
25976 \ ******************************\
25977 \ here return all interrupts \
25978 \ ******************************\
25982 \ ------------------------------\
25983 CODE STOP \ stops multitasking, must to be used before downloading app
25984 \ ------------------------------\
25985 \ restore default action of primary DEFERred word SLEEP (assembly version)
25986 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
25987 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25988 MOV X,-2(X) \ restore the default background
25989 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25990 ['] WARM >BODY IS WARM \ restore the default WARM
25992 ." RC5toLCD is removed. type START to restart"
25993 COLD \ performs reset to reset all interrupt vectors.
25996 \ ------------------------------\
25997 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
25998 \ ------------------------------\
25999 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
26000 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26001 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26002 \ -- \ID input divider \ 10 = /4
26003 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26004 \ - \TBCLR TimerB Clear
26007 \ -------------------------------\
26008 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26009 \ -- \CM Capture Mode
26014 \ --- \OUTMOD \ 011 = set/reset
26020 \ -------------------------------\
26022 \ -------------------------------\
26024 \ ------------------------------\
26025 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26026 \ ------------------------------\
26027 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26028 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26029 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
26030 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26032 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
26033 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26035 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
26036 \ ------------------------------\
26037 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26038 \ ------------------------------\
26039 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
26040 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26041 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26042 \ ------------------------------\
26043 BIS.B #LCDVo,&LCDVo_DIR \
26044 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
26045 \ ------------------------------\
26046 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26047 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26048 \ ------------------------------\
26049 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26050 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26051 \ ******************************\
26053 \ ******************************\
26054 BIS.B #RC5,&IR_IE \ enable RC5_Int
26055 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26056 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26057 \ ******************************\
26058 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26059 \ ******************************\
26060 \ %01 0001 0100 \ TAxCTL
26061 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
26062 \ -- \ ID divided by 1
26063 \ -- \ MC MODE = up to TAxCCRn
26064 \ - \ TACLR clear timer count
26067 \ ------------------------------\
26068 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
26069 \ ------------------------------\
26071 \ --- \ TAIDEX pre divisor
26072 \ ------------------------------\
26073 \ %0000 0000 0000 0101 \ TAxCCR0
26074 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26075 \ ------------------------------\
26076 \ %0000 0000 0001 0000 \ TAxCCTL0
26077 \ - \ CAP capture/compare mode = compare
26080 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
26081 \ ------------------------------\
26082 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26083 \ ------------------------------\
26084 \ define LPM mode for ACCEPT \
26085 \ ------------------------------\
26086 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26087 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26088 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26089 \ ------------------------------\
26091 \ ------------------------------\
26092 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
26093 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
26094 \ ------------------------------\
26095 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
26096 \ ------------------------------\
26097 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
26098 \ CMP #2,Y \ Power_ON event
26099 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
26101 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
26103 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
26105 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
26107 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
26108 \ ------------------------------\
26110 \ ------------------------------\
26112 \ ------------------------------\
26113 #1000 20_US \ 1- wait 20 ms
26114 %011 TOP_LCD \ 2- send DB5=DB4=1
26115 #205 20_US \ 3- wait 4,1 ms
26116 %011 TOP_LCD \ 4- send again DB5=DB4=1
26117 #5 20_US \ 5- wait 0,1 ms
26118 %011 TOP_LCD \ 6- send again again DB5=DB4=1
26119 #2 20_US \ wait 40 us = LCD cycle
26120 %010 TOP_LCD \ 7- send DB5=1 DB4=0
26121 #2 20_US \ wait 40 us = LCD cycle
26122 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26123 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26124 LCD_CLEAR \ 10- "LCD_Clear"
26125 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26126 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26127 LCD_CLEAR \ 10- "LCD_Clear"
26128 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26129 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26130 CR ." I love you" \ display message on LCD
26131 ['] CR >BODY IS CR \ CR executes its default value
26132 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
26133 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26134 ABORT \ ...and end APP_INIT with ABORT, no return.
26137 \ ------------------------------\
26138 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
26139 \ ------------------------------\
26140 MOV #SLEEP,X \ replace default background process
26141 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
26142 MOV #WARM,X \ replace default WARM
26143 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
26144 MOV X,PC \ then execute it
26147 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26151 CODE 20_US \ n -- n * 20 us
26152 BEGIN \ here we presume that LCD_TIM_IFG = 1...
26154 BIT #1,&LCD_TIM_CTL \ 3
26155 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
26156 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
26158 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
26163 CODE TOP_LCD \ LCD Sample
26164 \ \ if write : %xxxxWWWW --
26165 \ \ if read : -- %0000RRRR
26166 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26167 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26168 0= IF \ write LCD bits pattern
26169 AND.B #LCD_DB,TOS \
26170 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26171 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26174 THEN \ read LCD bits pattern
26177 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26178 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26179 AND.B #LCD_DB,TOS \
26183 CODE LCD_WRC \ char -- Write Char
26184 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26186 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26187 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26188 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26189 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26190 COLON \ high level word starts here
26191 TOP_LCD 2 20_US \ write high nibble first
26195 CODE LCD_WRF \ func -- Write Fonction
26196 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26200 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
26201 : LCD_HOME $02 LCD_WRF 100 20_us ;
26203 \ [UNDEFINED] OR [IF]
26205 \ \ https://forth-standard.org/standard/core/OR
26206 \ \ C OR x1 x2 -- x3 logical OR
26214 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
26215 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
26216 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
26217 \ : LCD_FN_SET $20 OR LCD_WrF ;
26218 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
26219 \ : LCD_GOTO $80 OR LCD_WrF ;
26222 \ CODE LCD_RDS \ -- status Read Status
26223 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26224 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26225 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26226 \ COLON \ starts a FORTH word
26227 \ TOP_LCD 2 20_us \ -- %0000HHHH
26228 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26229 \ HI2LO \ switch from FORTH to assembler
26230 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26231 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26232 \ MOV @RSP+,IP \ restore IP saved by COLON
26236 \ CODE LCD_RDC \ -- char Read Char
26237 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26242 \ ******************************\
26243 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26244 \ ******************************\
26245 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26246 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
26247 BIT.B #SW2,&SW2_IN \ test switch S2
26248 0= IF \ case of switch S2 pressed
26249 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26251 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
26254 BIT.B #SW1,&SW1_IN \ test switch S1 input
26255 0= IF \ case of Switch S1 pressed
26256 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26258 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26262 BW1 \ from quit on truncated RC5 message, repeated RC5 command
26266 \ ******************************\
26267 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26268 \ ******************************\
26269 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26270 \ ******************************\
26271 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26272 \ \ SMclock = 8|16|24 MHz
26273 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26274 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26275 \ \ SR(9)=new Toggle bit memory (ADD on)
26276 \ ******************************\
26277 \ RC5_FirstStartBitHalfCycle: \
26278 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26279 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26280 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
26281 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
26283 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
26284 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
26286 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
26287 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
26289 MOV #1778,X \ RC5_Period * 1us
26290 MOV #14,W \ count of loop
26292 \ ******************************\
26293 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
26294 \ ******************************\ |
26295 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26296 \ RC5_Compute_3/4_Period: \ |
26297 RRUM #1,X \ X=1/2 cycle |
26300 ADD X,Y \ Y=3/4 cycle
26301 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
26303 \ ******************************\
26304 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26305 \ ******************************\
26306 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26307 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
26308 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26309 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26310 SUB #1,W \ decrement count loop
26311 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
26312 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26313 0<> WHILE \ ----> out of loop ----+
26314 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26316 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
26317 CMP Y,X \ 1 | cycle time out of bound ?
26318 U>= IF \ 2 ^ | yes:
26319 BIC #$30,&RC5_TIM_CTL \ | | stop timer
26320 GOTO BW1 \ | | quit on truncated RC5 message
26322 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
26324 REPEAT \ ----> loop back --+ | with X = new RC5_period value
26325 \ ******************************\ |
26326 \ RC5_SampleEndOf: \ <---------------------+
26327 \ ******************************\
26328 BIC #$30,&RC5_TIM_CTL \ stop timer
26329 \ ******************************\
26330 \ RC5_ComputeNewRC5word \
26331 \ ******************************\
26332 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
26333 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
26334 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
26335 \ ******************************\
26336 \ RC5_ComputeC6bit \
26337 \ ******************************\
26338 BIT #BIT14,T \ test /C6 bit in T
26339 0= IF BIS #BIT6,X \ set C6 bit in X
26340 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
26341 \ ******************************\
26342 \ RC5_CommandByteIsDone \ -- BASE RC5_code
26343 \ ******************************\
26344 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26345 \ ******************************\
26346 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
26347 XOR @RSP,T \ (new XOR old) Toggle bits
26348 BIT #UF10,T \ repeated RC5_command ?
26349 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
26350 XOR #UF10,0(RSP) \ 5 toggle bit memory
26351 \ ******************************\
26352 \ Display IR_RC5 code \
26353 \ ******************************\
26354 SUB #8,PSP \ TOS -- x x x x TOS
26355 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
26356 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
26357 MOV #$10,&BASEADR \ set hexadecimal base
26358 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
26359 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
26360 LO2HI \ switch from assembler to FORTH
26361 LCD_CLEAR \ set LCD cursor at home
26362 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
26363 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
26364 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
26365 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
26366 HI2LO \ -- switch from FORTH to assembler
26367 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
26368 MOV @PSP+,TOS \ -- TOS
26372 \ ------------------------------\
26374 \ ------------------------------\
26376 \ ... \ insert here your background task
26379 CALL &RXON \ comment this line to disable TERMINAL
26381 \ ******************************\
26382 \ here start all interrupts \
26383 \ ******************************\
26384 \ here return all interrupts \
26385 \ ******************************\
26389 \ ------------------------------\
26390 CODE STOP \ stops multitasking, must to be used before downloading app
26391 \ ------------------------------\
26392 \ restore default action of primary DEFERred word SLEEP (assembly version)
26393 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
26394 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
26395 MOV X,-2(X) \ restore the default background
26396 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
26397 ['] WARM >BODY IS WARM \ restore the default WARM
26399 ." RC5toLCD is removed. type START to restart"
26400 COLD \ performs reset to reset all interrupt vectors.
26403 \ ------------------------------\
26404 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
26405 \ ------------------------------\
26406 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
26407 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26408 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26409 \ -- \ID input divider \ 10 = /4
26410 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26411 \ - \TBCLR TimerB Clear
26414 \ -------------------------------\
26415 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26416 \ -- \CM Capture Mode
26421 \ --- \OUTMOD \ 011 = set/reset
26427 \ -------------------------------\
26429 \ -------------------------------\
26431 \ ------------------------------\
26432 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26433 \ ------------------------------\
26434 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26435 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26436 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
26437 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26439 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
26440 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26442 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
26443 \ ------------------------------\
26444 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26445 \ ------------------------------\
26446 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
26447 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26448 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26449 \ ------------------------------\
26450 BIS.B #LCDVo,&LCDVo_DIR \
26451 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
26452 \ ------------------------------\
26453 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26454 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26455 \ ------------------------------\
26456 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26457 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26458 \ ******************************\
26460 \ ******************************\
26461 BIS.B #RC5,&IR_IE \ enable RC5_Int
26462 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26463 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26464 \ ******************************\
26465 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26466 \ ******************************\
26467 \ %01 0001 0100 \ TAxCTL
26468 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
26469 \ -- \ ID divided by 1
26470 \ -- \ MC MODE = up to TAxCCRn
26471 \ - \ TACLR clear timer count
26474 \ ------------------------------\
26475 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
26476 \ ------------------------------\
26478 \ --- \ TAIDEX pre divisor
26479 \ ------------------------------\
26480 \ %0000 0000 0000 0101 \ TAxCCR0
26481 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26482 \ ------------------------------\
26483 \ %0000 0000 0001 0000 \ TAxCCTL0
26484 \ - \ CAP capture/compare mode = compare
26487 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
26488 \ ------------------------------\
26489 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26490 \ ------------------------------\
26491 \ define LPM mode for ACCEPT \
26492 \ ------------------------------\
26493 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26494 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26495 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26496 \ ------------------------------\
26498 \ ------------------------------\
26499 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
26500 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
26501 \ ------------------------------\
26502 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
26503 \ ------------------------------\
26504 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
26505 \ CMP #2,Y \ Power_ON event
26506 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
26508 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
26510 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
26512 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
26514 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
26515 \ ------------------------------\
26517 \ ------------------------------\
26519 \ ------------------------------\
26520 #1000 20_US \ 1- wait 20 ms
26521 %011 TOP_LCD \ 2- send DB5=DB4=1
26522 #205 20_US \ 3- wait 4,1 ms
26523 %011 TOP_LCD \ 4- send again DB5=DB4=1
26524 #5 20_US \ 5- wait 0,1 ms
26525 %011 TOP_LCD \ 6- send again again DB5=DB4=1
26526 #2 20_US \ wait 40 us = LCD cycle
26527 %010 TOP_LCD \ 7- send DB5=1 DB4=0
26528 #2 20_US \ wait 40 us = LCD cycle
26529 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26530 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26531 LCD_CLEAR \ 10- "LCD_Clear"
26532 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26533 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26534 LCD_CLEAR \ 10- "LCD_Clear"
26535 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26536 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26537 CR ." I love you" \ display message on LCD
26538 ['] CR >BODY IS CR \ CR executes its default value
26539 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
26540 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26541 ABORT \ ...and end APP_INIT with ABORT, no return.
26544 \ ------------------------------\
26545 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
26546 \ ------------------------------\
26547 MOV #SLEEP,X \ replace default background process
26548 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
26549 MOV #WARM,X \ replace default WARM
26550 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
26551 MOV X,PC \ then execute it
26554 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26558 CODE 20_US \ n -- n * 20 us
26559 BEGIN \ here we presume that LCD_TIM_IFG = 1...
26561 BIT #1,&LCD_TIM_CTL \ 3
26562 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
26563 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
26565 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
26570 CODE TOP_LCD \ LCD Sample
26571 \ \ if write : %xxxxWWWW --
26572 \ \ if read : -- %0000RRRR
26573 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26574 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26575 0= IF \ write LCD bits pattern
26576 AND.B #LCD_DB,TOS \
26577 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26578 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26581 THEN \ read LCD bits pattern
26584 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26585 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26586 AND.B #LCD_DB,TOS \
26590 CODE LCD_WRC \ char -- Write Char
26591 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26593 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26594 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26595 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26596 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26597 COLON \ high level word starts here
26598 TOP_LCD 2 20_US \ write high nibble first
26602 CODE LCD_WRF \ func -- Write Fonction
26603 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26607 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
26608 : LCD_HOME $02 LCD_WRF 100 20_us ;
26610 \ [UNDEFINED] OR [IF]
26612 \ \ https://forth-standard.org/standard/core/OR
26613 \ \ C OR x1 x2 -- x3 logical OR
26621 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
26622 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
26623 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
26624 \ : LCD_FN_SET $20 OR LCD_WrF ;
26625 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
26626 \ : LCD_GOTO $80 OR LCD_WrF ;
26629 \ CODE LCD_RDS \ -- status Read Status
26630 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26631 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26632 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26633 \ COLON \ starts a FORTH word
26634 \ TOP_LCD 2 20_us \ -- %0000HHHH
26635 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26636 \ HI2LO \ switch from FORTH to assembler
26637 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26638 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26639 \ MOV @RSP+,IP \ restore IP saved by COLON
26643 \ CODE LCD_RDC \ -- char Read Char
26644 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26649 \ ******************************\
26650 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26651 \ ******************************\
26652 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26653 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
26654 BIT.B #SW2,&SW2_IN \ test switch S2
26655 0= IF \ case of switch S2 pressed
26656 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26658 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
26661 BIT.B #SW1,&SW1_IN \ test switch S1 input
26662 0= IF \ case of Switch S1 pressed
26663 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26665 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26669 BW1 \ from quit on truncated RC5 message, repeated RC5 command
26673 \ ******************************\
26674 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26675 \ ******************************\
26676 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26677 \ ******************************\
26678 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26679 \ \ SMclock = 8|16|24 MHz
26680 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26681 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26682 \ \ SR(9)=new Toggle bit memory (ADD on)
26683 \ ******************************\
26684 \ RC5_FirstStartBitHalfCycle: \
26685 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26686 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26687 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
26688 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
26690 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
26691 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
26693 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
26694 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
26696 MOV #1778,X \ RC5_Period * 1us
26697 MOV #14,W \ count of loop
26699 \ ******************************\
26700 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
26701 \ ******************************\ |
26702 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26703 \ RC5_Compute_3/4_Period: \ |
26704 RRUM #1,X \ X=1/2 cycle |
26707 ADD X,Y \ Y=3/4 cycle
26708 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
26710 \ ******************************\
26711 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26712 \ ******************************\
26713 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26714 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
26715 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26716 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26717 SUB #1,W \ decrement count loop
26718 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
26719 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26720 0<> WHILE \ ----> out of loop ----+
26721 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26723 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
26724 CMP Y,X \ 1 | cycle time out of bound ?
26725 U>= IF \ 2 ^ | yes:
26726 BIC #$30,&RC5_TIM_CTL \ | | stop timer
26727 GOTO BW1 \ | | quit on truncated RC5 message
26729 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
26731 REPEAT \ ----> loop back --+ | with X = new RC5_period value
26732 \ ******************************\ |
26733 \ RC5_SampleEndOf: \ <---------------------+
26734 \ ******************************\
26735 BIC #$30,&RC5_TIM_CTL \ stop timer
26736 \ ******************************\
26737 \ RC5_ComputeNewRC5word \
26738 \ ******************************\
26739 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
26740 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
26741 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
26742 \ ******************************\
26743 \ RC5_ComputeC6bit \
26744 \ ******************************\
26745 BIT #BIT14,T \ test /C6 bit in T
26746 0= IF BIS #BIT6,X \ set C6 bit in X
26747 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
26748 \ ******************************\
26749 \ RC5_CommandByteIsDone \ -- BASE RC5_code
26750 \ ******************************\
26751 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26752 \ ******************************\
26753 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
26754 XOR @RSP,T \ (new XOR old) Toggle bits
26755 BIT #UF10,T \ repeated RC5_command ?
26756 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
26757 XOR #UF10,0(RSP) \ 5 toggle bit memory
26758 \ ******************************\
26759 \ Display IR_RC5 code \
26760 \ ******************************\
26761 SUB #8,PSP \ TOS -- x x x x TOS
26762 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
26763 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
26764 MOV #$10,&BASEADR \ set hexadecimal base
26765 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
26766 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
26767 LO2HI \ switch from assembler to FORTH
26768 LCD_CLEAR \ set LCD cursor at home
26769 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
26770 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
26771 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
26772 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
26773 HI2LO \ -- switch from FORTH to assembler
26774 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
26775 MOV @PSP+,TOS \ -- TOS
26779 \ ------------------------------\
26781 \ ------------------------------\
26783 \ ... \ insert here your background task
26786 CALL &RXON \ comment this line to disable TERMINAL
26788 \ ******************************\
26789 \ here start all interrupts \
26790 \ ******************************\
26791 \ here return all interrupts \
26792 \ ******************************\
26796 \ ------------------------------\
26797 CODE STOP \ stops multitasking, must to be used before downloading app
26798 \ ------------------------------\
26799 \ restore default action of primary DEFERred word SLEEP (assembly version)
26800 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
26801 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
26802 MOV X,-2(X) \ restore the default background
26803 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
26804 ['] WARM >BODY IS WARM \ restore the default WARM
26806 ." RC5toLCD is removed. type START to restart"
26807 COLD \ performs reset to reset all interrupt vectors.
26810 \ ------------------------------\
26811 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
26812 \ ------------------------------\
26813 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
26814 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26815 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26816 \ -- \ID input divider \ 10 = /4
26817 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26818 \ - \TBCLR TimerB Clear
26821 \ -------------------------------\
26822 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26823 \ -- \CM Capture Mode
26828 \ --- \OUTMOD \ 011 = set/reset
26834 \ -------------------------------\
26836 \ -------------------------------\
26838 \ ------------------------------\
26839 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26840 \ ------------------------------\
26841 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26842 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26843 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
26844 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26846 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
26847 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26849 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
26850 \ ------------------------------\
26851 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26852 \ ------------------------------\
26853 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
26854 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26855 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26856 \ ------------------------------\
26857 BIS.B #LCDVo,&LCDVo_DIR \
26858 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
26859 \ ------------------------------\
26860 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26861 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26862 \ ------------------------------\
26863 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26864 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26865 \ ******************************\
26867 \ ******************************\
26868 BIS.B #RC5,&IR_IE \ enable RC5_Int
26869 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26870 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26871 \ ******************************\
26872 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26873 \ ******************************\
26874 \ %01 0001 0100 \ TAxCTL
26875 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
26876 \ -- \ ID divided by 1
26877 \ -- \ MC MODE = up to TAxCCRn
26878 \ - \ TACLR clear timer count
26881 \ ------------------------------\
26882 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
26883 \ ------------------------------\
26885 \ --- \ TAIDEX pre divisor
26886 \ ------------------------------\
26887 \ %0000 0000 0000 0101 \ TAxCCR0
26888 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26889 \ ------------------------------\
26890 \ %0000 0000 0001 0000 \ TAxCCTL0
26891 \ - \ CAP capture/compare mode = compare
26894 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
26895 \ ------------------------------\
26896 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26897 \ ------------------------------\
26898 \ define LPM mode for ACCEPT \
26899 \ ------------------------------\
26900 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26901 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26902 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26903 \ ------------------------------\
26905 \ ------------------------------\
26906 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
26907 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
26908 \ ------------------------------\
26909 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
26910 \ ------------------------------\
26911 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
26912 \ CMP #2,Y \ Power_ON event
26913 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
26915 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
26917 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
26919 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
26921 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
26922 \ ------------------------------\
26924 \ ------------------------------\
26926 \ ------------------------------\
26927 #1000 20_US \ 1- wait 20 ms
26928 %011 TOP_LCD \ 2- send DB5=DB4=1
26929 #205 20_US \ 3- wait 4,1 ms
26930 %011 TOP_LCD \ 4- send again DB5=DB4=1
26931 #5 20_US \ 5- wait 0,1 ms
26932 %011 TOP_LCD \ 6- send again again DB5=DB4=1
26933 #2 20_US \ wait 40 us = LCD cycle
26934 %010 TOP_LCD \ 7- send DB5=1 DB4=0
26935 #2 20_US \ wait 40 us = LCD cycle
26936 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26937 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26938 LCD_CLEAR \ 10- "LCD_Clear"
26939 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26940 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26941 LCD_CLEAR \ 10- "LCD_Clear"
26942 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26943 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26944 CR ." I love you" \ display message on LCD
26945 ['] CR >BODY IS CR \ CR executes its default value
26946 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
26947 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26948 ABORT \ ...and end APP_INIT with ABORT, no return.
26951 \ ------------------------------\
26952 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
26953 \ ------------------------------\
26954 MOV #SLEEP,X \ replace default background process
26955 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
26956 MOV #WARM,X \ replace default WARM
26957 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
26958 MOV X,PC \ then execute it
26961 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26965 CODE 20_US \ n -- n * 20 us
26966 BEGIN \ here we presume that LCD_TIM_IFG = 1...
26968 BIT #1,&LCD_TIM_CTL \ 3
26969 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
26970 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
26972 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
26977 CODE TOP_LCD \ LCD Sample
26978 \ \ if write : %xxxxWWWW --
26979 \ \ if read : -- %0000RRRR
26980 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26981 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26982 0= IF \ write LCD bits pattern
26983 AND.B #LCD_DB,TOS \
26984 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26985 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26988 THEN \ read LCD bits pattern
26991 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26992 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26993 AND.B #LCD_DB,TOS \
26997 CODE LCD_WRC \ char -- Write Char
26998 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27000 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27001 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27002 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27003 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27004 COLON \ high level word starts here
27005 TOP_LCD 2 20_US \ write high nibble first
27009 CODE LCD_WRF \ func -- Write Fonction
27010 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27014 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
27015 : LCD_HOME $02 LCD_WRF 100 20_us ;
27017 \ [UNDEFINED] OR [IF]
27019 \ \ https://forth-standard.org/standard/core/OR
27020 \ \ C OR x1 x2 -- x3 logical OR
27028 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
27029 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
27030 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
27031 \ : LCD_FN_SET $20 OR LCD_WrF ;
27032 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
27033 \ : LCD_GOTO $80 OR LCD_WrF ;
27036 \ CODE LCD_RDS \ -- status Read Status
27037 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27038 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27039 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27040 \ COLON \ starts a FORTH word
27041 \ TOP_LCD 2 20_us \ -- %0000HHHH
27042 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27043 \ HI2LO \ switch from FORTH to assembler
27044 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27045 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27046 \ MOV @RSP+,IP \ restore IP saved by COLON
27050 \ CODE LCD_RDC \ -- char Read Char
27051 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27056 \ ******************************\
27057 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27058 \ ******************************\
27059 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27060 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
27061 BIT.B #SW2,&SW2_IN \ test switch S2
27062 0= IF \ case of switch S2 pressed
27063 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27065 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
27068 BIT.B #SW1,&SW1_IN \ test switch S1 input
27069 0= IF \ case of Switch S1 pressed
27070 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27072 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27076 BW1 \ from quit on truncated RC5 message, repeated RC5 command
27080 \ ******************************\
27081 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27082 \ ******************************\
27083 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27084 \ ******************************\
27085 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27086 \ \ SMclock = 8|16|24 MHz
27087 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27088 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27089 \ \ SR(9)=new Toggle bit memory (ADD on)
27090 \ ******************************\
27091 \ RC5_FirstStartBitHalfCycle: \
27092 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27093 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27094 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
27095 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
27097 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
27098 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
27100 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
27101 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
27103 MOV #1778,X \ RC5_Period * 1us
27104 MOV #14,W \ count of loop
27106 \ ******************************\
27107 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
27108 \ ******************************\ |
27109 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27110 \ RC5_Compute_3/4_Period: \ |
27111 RRUM #1,X \ X=1/2 cycle |
27114 ADD X,Y \ Y=3/4 cycle
27115 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
27117 \ ******************************\
27118 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27119 \ ******************************\
27120 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27121 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
27122 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27123 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27124 SUB #1,W \ decrement count loop
27125 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
27126 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27127 0<> WHILE \ ----> out of loop ----+
27128 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27130 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
27131 CMP Y,X \ 1 | cycle time out of bound ?
27132 U>= IF \ 2 ^ | yes:
27133 BIC #$30,&RC5_TIM_CTL \ | | stop timer
27134 GOTO BW1 \ | | quit on truncated RC5 message
27136 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
27138 REPEAT \ ----> loop back --+ | with X = new RC5_period value
27139 \ ******************************\ |
27140 \ RC5_SampleEndOf: \ <---------------------+
27141 \ ******************************\
27142 BIC #$30,&RC5_TIM_CTL \ stop timer
27143 \ ******************************\
27144 \ RC5_ComputeNewRC5word \
27145 \ ******************************\
27146 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
27147 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27148 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27149 \ ******************************\
27150 \ RC5_ComputeC6bit \
27151 \ ******************************\
27152 BIT #BIT14,T \ test /C6 bit in T
27153 0= IF BIS #BIT6,X \ set C6 bit in X
27154 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27155 \ ******************************\
27156 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27157 \ ******************************\
27158 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27159 \ ******************************\
27160 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27161 XOR @RSP,T \ (new XOR old) Toggle bits
27162 BIT #UF10,T \ repeated RC5_command ?
27163 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
27164 XOR #UF10,0(RSP) \ 5 toggle bit memory
27165 \ ******************************\
27166 \ Display IR_RC5 code \
27167 \ ******************************\
27168 SUB #8,PSP \ TOS -- x x x x TOS
27169 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27170 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27171 MOV #$10,&BASEADR \ set hexadecimal base
27172 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27173 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27174 LO2HI \ switch from assembler to FORTH
27175 LCD_CLEAR \ set LCD cursor at home
27176 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27177 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27178 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27179 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27180 HI2LO \ -- switch from FORTH to assembler
27181 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27182 MOV @PSP+,TOS \ -- TOS
27186 \ ------------------------------\
27188 \ ------------------------------\
27190 \ ... \ insert here your background task
27193 CALL &RXON \ comment this line to disable TERMINAL
27195 \ ******************************\
27196 \ here start all interrupts \
27197 \ ******************************\
27198 \ here return all interrupts \
27199 \ ******************************\
27203 \ ------------------------------\
27204 CODE STOP \ stops multitasking, must to be used before downloading app
27205 \ ------------------------------\
27206 \ restore default action of primary DEFERred word SLEEP (assembly version)
27207 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
27208 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
27209 MOV X,-2(X) \ restore the default background
27210 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
27211 ['] WARM >BODY IS WARM \ restore the default WARM
27213 ." RC5toLCD is removed. type START to restart"
27214 COLD \ performs reset to reset all interrupt vectors.
27217 \ ------------------------------\
27218 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
27219 \ ------------------------------\
27220 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
27221 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27222 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27223 \ -- \ID input divider \ 10 = /4
27224 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27225 \ - \TBCLR TimerB Clear
27228 \ -------------------------------\
27229 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27230 \ -- \CM Capture Mode
27235 \ --- \OUTMOD \ 011 = set/reset
27241 \ -------------------------------\
27243 \ -------------------------------\
27245 \ ------------------------------\
27246 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27247 \ ------------------------------\
27248 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27249 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27250 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
27251 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27253 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
27254 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27256 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
27257 \ ------------------------------\
27258 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27259 \ ------------------------------\
27260 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
27261 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27262 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27263 \ ------------------------------\
27264 BIS.B #LCDVo,&LCDVo_DIR \
27265 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
27266 \ ------------------------------\
27267 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27268 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27269 \ ------------------------------\
27270 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27271 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27272 \ ******************************\
27274 \ ******************************\
27275 BIS.B #RC5,&IR_IE \ enable RC5_Int
27276 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27277 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27278 \ ******************************\
27279 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27280 \ ******************************\
27281 \ %01 0001 0100 \ TAxCTL
27282 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
27283 \ -- \ ID divided by 1
27284 \ -- \ MC MODE = up to TAxCCRn
27285 \ - \ TACLR clear timer count
27288 \ ------------------------------\
27289 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
27290 \ ------------------------------\
27292 \ --- \ TAIDEX pre divisor
27293 \ ------------------------------\
27294 \ %0000 0000 0000 0101 \ TAxCCR0
27295 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27296 \ ------------------------------\
27297 \ %0000 0000 0001 0000 \ TAxCCTL0
27298 \ - \ CAP capture/compare mode = compare
27301 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
27302 \ ------------------------------\
27303 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27304 \ ------------------------------\
27305 \ define LPM mode for ACCEPT \
27306 \ ------------------------------\
27307 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27308 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27309 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27310 \ ------------------------------\
27312 \ ------------------------------\
27313 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
27314 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
27315 \ ------------------------------\
27316 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
27317 \ ------------------------------\
27318 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
27319 \ CMP #2,Y \ Power_ON event
27320 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
27322 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
27324 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
27326 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
27328 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
27329 \ ------------------------------\
27331 \ ------------------------------\
27333 \ ------------------------------\
27334 #1000 20_US \ 1- wait 20 ms
27335 %011 TOP_LCD \ 2- send DB5=DB4=1
27336 #205 20_US \ 3- wait 4,1 ms
27337 %011 TOP_LCD \ 4- send again DB5=DB4=1
27338 #5 20_US \ 5- wait 0,1 ms
27339 %011 TOP_LCD \ 6- send again again DB5=DB4=1
27340 #2 20_US \ wait 40 us = LCD cycle
27341 %010 TOP_LCD \ 7- send DB5=1 DB4=0
27342 #2 20_US \ wait 40 us = LCD cycle
27343 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27344 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27345 LCD_CLEAR \ 10- "LCD_Clear"
27346 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27347 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27348 LCD_CLEAR \ 10- "LCD_Clear"
27349 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27350 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27351 CR ." I love you" \ display message on LCD
27352 ['] CR >BODY IS CR \ CR executes its default value
27353 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
27354 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27355 ABORT \ ...and end APP_INIT with ABORT, no return.
27358 \ ------------------------------\
27359 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
27360 \ ------------------------------\
27361 MOV #SLEEP,X \ replace default background process
27362 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
27363 MOV #WARM,X \ replace default WARM
27364 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
27365 MOV X,PC \ then execute it
27368 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
27372 CODE 20_US \ n -- n * 20 us
27373 BEGIN \ here we presume that LCD_TIM_IFG = 1...
27375 BIT #1,&LCD_TIM_CTL \ 3
27376 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
27377 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
27379 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
27384 CODE TOP_LCD \ LCD Sample
27385 \ \ if write : %xxxxWWWW --
27386 \ \ if read : -- %0000RRRR
27387 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27388 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27389 0= IF \ write LCD bits pattern
27390 AND.B #LCD_DB,TOS \
27391 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27392 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27395 THEN \ read LCD bits pattern
27398 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27399 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27400 AND.B #LCD_DB,TOS \
27404 CODE LCD_WRC \ char -- Write Char
27405 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27407 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27408 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27409 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27410 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27411 COLON \ high level word starts here
27412 TOP_LCD 2 20_US \ write high nibble first
27416 CODE LCD_WRF \ func -- Write Fonction
27417 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27421 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
27422 : LCD_HOME $02 LCD_WRF 100 20_us ;
27424 \ [UNDEFINED] OR [IF]
27426 \ \ https://forth-standard.org/standard/core/OR
27427 \ \ C OR x1 x2 -- x3 logical OR
27435 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
27436 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
27437 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
27438 \ : LCD_FN_SET $20 OR LCD_WrF ;
27439 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
27440 \ : LCD_GOTO $80 OR LCD_WrF ;
27443 \ CODE LCD_RDS \ -- status Read Status
27444 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27445 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27446 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27447 \ COLON \ starts a FORTH word
27448 \ TOP_LCD 2 20_us \ -- %0000HHHH
27449 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27450 \ HI2LO \ switch from FORTH to assembler
27451 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27452 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27453 \ MOV @RSP+,IP \ restore IP saved by COLON
27457 \ CODE LCD_RDC \ -- char Read Char
27458 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27463 \ ******************************\
27464 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27465 \ ******************************\
27466 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27467 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
27468 BIT.B #SW2,&SW2_IN \ test switch S2
27469 0= IF \ case of switch S2 pressed
27470 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27472 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
27475 BIT.B #SW1,&SW1_IN \ test switch S1 input
27476 0= IF \ case of Switch S1 pressed
27477 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27479 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27483 BW1 \ from quit on truncated RC5 message, repeated RC5 command
27487 \ ******************************\
27488 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27489 \ ******************************\
27490 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27491 \ ******************************\
27492 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27493 \ \ SMclock = 8|16|24 MHz
27494 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27495 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27496 \ \ SR(9)=new Toggle bit memory (ADD on)
27497 \ ******************************\
27498 \ RC5_FirstStartBitHalfCycle: \
27499 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27500 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27501 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
27502 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
27504 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
27505 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
27507 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
27508 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
27510 MOV #1778,X \ RC5_Period * 1us
27511 MOV #14,W \ count of loop
27513 \ ******************************\
27514 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
27515 \ ******************************\ |
27516 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27517 \ RC5_Compute_3/4_Period: \ |
27518 RRUM #1,X \ X=1/2 cycle |
27521 ADD X,Y \ Y=3/4 cycle
27522 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
27524 \ ******************************\
27525 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27526 \ ******************************\
27527 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27528 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
27529 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27530 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27531 SUB #1,W \ decrement count loop
27532 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
27533 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27534 0<> WHILE \ ----> out of loop ----+
27535 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27537 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
27538 CMP Y,X \ 1 | cycle time out of bound ?
27539 U>= IF \ 2 ^ | yes:
27540 BIC #$30,&RC5_TIM_CTL \ | | stop timer
27541 GOTO BW1 \ | | quit on truncated RC5 message
27543 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
27545 REPEAT \ ----> loop back --+ | with X = new RC5_period value
27546 \ ******************************\ |
27547 \ RC5_SampleEndOf: \ <---------------------+
27548 \ ******************************\
27549 BIC #$30,&RC5_TIM_CTL \ stop timer
27550 \ ******************************\
27551 \ RC5_ComputeNewRC5word \
27552 \ ******************************\
27553 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
27554 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27555 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27556 \ ******************************\
27557 \ RC5_ComputeC6bit \
27558 \ ******************************\
27559 BIT #BIT14,T \ test /C6 bit in T
27560 0= IF BIS #BIT6,X \ set C6 bit in X
27561 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27562 \ ******************************\
27563 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27564 \ ******************************\
27565 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27566 \ ******************************\
27567 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27568 XOR @RSP,T \ (new XOR old) Toggle bits
27569 BIT #UF10,T \ repeated RC5_command ?
27570 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
27571 XOR #UF10,0(RSP) \ 5 toggle bit memory
27572 \ ******************************\
27573 \ Display IR_RC5 code \
27574 \ ******************************\
27575 SUB #8,PSP \ TOS -- x x x x TOS
27576 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27577 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27578 MOV #$10,&BASEADR \ set hexadecimal base
27579 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27580 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27581 LO2HI \ switch from assembler to FORTH
27582 LCD_CLEAR \ set LCD cursor at home
27583 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27584 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27585 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27586 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27587 HI2LO \ -- switch from FORTH to assembler
27588 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27589 MOV @PSP+,TOS \ -- TOS
27593 \ ------------------------------\
27595 \ ------------------------------\
27597 \ ... \ insert here your background task
27600 CALL &RXON \ comment this line to disable TERMINAL
27602 \ ******************************\
27603 \ here start all interrupts \
27604 \ ******************************\
27605 \ here return all interrupts \
27606 \ ******************************\
27610 \ ------------------------------\
27611 CODE STOP \ stops multitasking, must to be used before downloading app
27612 \ ------------------------------\
27613 \ restore default action of primary DEFERred word SLEEP (assembly version)
27614 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
27615 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
27616 MOV X,-2(X) \ restore the default background
27617 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
27618 ['] WARM >BODY IS WARM \ restore the default WARM
27620 ." RC5toLCD is removed. type START to restart"
27621 COLD \ performs reset to reset all interrupt vectors.
27624 \ ------------------------------\
27625 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
27626 \ ------------------------------\
27627 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
27628 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27629 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27630 \ -- \ID input divider \ 10 = /4
27631 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27632 \ - \TBCLR TimerB Clear
27635 \ -------------------------------\
27636 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27637 \ -- \CM Capture Mode
27642 \ --- \OUTMOD \ 011 = set/reset
27648 \ -------------------------------\
27650 \ -------------------------------\
27652 \ ------------------------------\
27653 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27654 \ ------------------------------\
27655 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27656 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27657 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
27658 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27660 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
27661 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27663 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
27664 \ ------------------------------\
27665 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27666 \ ------------------------------\
27667 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
27668 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27669 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27670 \ ------------------------------\
27671 BIS.B #LCDVo,&LCDVo_DIR \
27672 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
27673 \ ------------------------------\
27674 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27675 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27676 \ ------------------------------\
27677 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27678 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27679 \ ******************************\
27681 \ ******************************\
27682 BIS.B #RC5,&IR_IE \ enable RC5_Int
27683 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27684 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27685 \ ******************************\
27686 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27687 \ ******************************\
27688 \ %01 0001 0100 \ TAxCTL
27689 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
27690 \ -- \ ID divided by 1
27691 \ -- \ MC MODE = up to TAxCCRn
27692 \ - \ TACLR clear timer count
27695 \ ------------------------------\
27696 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
27697 \ ------------------------------\
27699 \ --- \ TAIDEX pre divisor
27700 \ ------------------------------\
27701 \ %0000 0000 0000 0101 \ TAxCCR0
27702 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27703 \ ------------------------------\
27704 \ %0000 0000 0001 0000 \ TAxCCTL0
27705 \ - \ CAP capture/compare mode = compare
27708 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
27709 \ ------------------------------\
27710 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27711 \ ------------------------------\
27712 \ define LPM mode for ACCEPT \
27713 \ ------------------------------\
27714 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27715 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27716 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27717 \ ------------------------------\
27719 \ ------------------------------\
27720 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
27721 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
27722 \ ------------------------------\
27723 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
27724 \ ------------------------------\
27725 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
27726 \ CMP #2,Y \ Power_ON event
27727 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
27729 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
27731 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
27733 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
27735 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
27736 \ ------------------------------\
27738 \ ------------------------------\
27740 \ ------------------------------\
27741 #1000 20_US \ 1- wait 20 ms
27742 %011 TOP_LCD \ 2- send DB5=DB4=1
27743 #205 20_US \ 3- wait 4,1 ms
27744 %011 TOP_LCD \ 4- send again DB5=DB4=1
27745 #5 20_US \ 5- wait 0,1 ms
27746 %011 TOP_LCD \ 6- send again again DB5=DB4=1
27747 #2 20_US \ wait 40 us = LCD cycle
27748 %010 TOP_LCD \ 7- send DB5=1 DB4=0
27749 #2 20_US \ wait 40 us = LCD cycle
27750 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27751 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27752 LCD_CLEAR \ 10- "LCD_Clear"
27753 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27754 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27755 LCD_CLEAR \ 10- "LCD_Clear"
27756 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27757 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27758 CR ." I love you" \ display message on LCD
27759 ['] CR >BODY IS CR \ CR executes its default value
27760 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
27761 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27762 ABORT \ ...and end APP_INIT with ABORT, no return.
27765 \ ------------------------------\
27766 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
27767 \ ------------------------------\
27768 MOV #SLEEP,X \ replace default background process
27769 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
27770 MOV #WARM,X \ replace default WARM
27771 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
27772 MOV X,PC \ then execute it
27775 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
27779 CODE 20_US \ n -- n * 20 us
27780 BEGIN \ here we presume that LCD_TIM_IFG = 1...
27782 BIT #1,&LCD_TIM_CTL \ 3
27783 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
27784 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
27786 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
27791 CODE TOP_LCD \ LCD Sample
27792 \ \ if write : %xxxxWWWW --
27793 \ \ if read : -- %0000RRRR
27794 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27795 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27796 0= IF \ write LCD bits pattern
27797 AND.B #LCD_DB,TOS \
27798 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27799 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27802 THEN \ read LCD bits pattern
27805 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27806 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27807 AND.B #LCD_DB,TOS \
27811 CODE LCD_WRC \ char -- Write Char
27812 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27814 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27815 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27816 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27817 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27818 COLON \ high level word starts here
27819 TOP_LCD 2 20_US \ write high nibble first
27823 CODE LCD_WRF \ func -- Write Fonction
27824 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27828 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
27829 : LCD_HOME $02 LCD_WRF 100 20_us ;
27831 \ [UNDEFINED] OR [IF]
27833 \ \ https://forth-standard.org/standard/core/OR
27834 \ \ C OR x1 x2 -- x3 logical OR
27842 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
27843 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
27844 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
27845 \ : LCD_FN_SET $20 OR LCD_WrF ;
27846 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
27847 \ : LCD_GOTO $80 OR LCD_WrF ;
27850 \ CODE LCD_RDS \ -- status Read Status
27851 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27852 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27853 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27854 \ COLON \ starts a FORTH word
27855 \ TOP_LCD 2 20_us \ -- %0000HHHH
27856 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27857 \ HI2LO \ switch from FORTH to assembler
27858 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27859 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27860 \ MOV @RSP+,IP \ restore IP saved by COLON
27864 \ CODE LCD_RDC \ -- char Read Char
27865 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27870 \ ******************************\
27871 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27872 \ ******************************\
27873 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27874 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
27875 BIT.B #SW2,&SW2_IN \ test switch S2
27876 0= IF \ case of switch S2 pressed
27877 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27879 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
27882 BIT.B #SW1,&SW1_IN \ test switch S1 input
27883 0= IF \ case of Switch S1 pressed
27884 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27886 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27890 BW1 \ from quit on truncated RC5 message, repeated RC5 command
27894 \ ******************************\
27895 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27896 \ ******************************\
27897 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27898 \ ******************************\
27899 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27900 \ \ SMclock = 8|16|24 MHz
27901 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27902 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27903 \ \ SR(9)=new Toggle bit memory (ADD on)
27904 \ ******************************\
27905 \ RC5_FirstStartBitHalfCycle: \
27906 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27907 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27908 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
27909 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
27911 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
27912 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
27914 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
27915 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
27917 MOV #1778,X \ RC5_Period * 1us
27918 MOV #14,W \ count of loop
27920 \ ******************************\
27921 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
27922 \ ******************************\ |
27923 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27924 \ RC5_Compute_3/4_Period: \ |
27925 RRUM #1,X \ X=1/2 cycle |
27928 ADD X,Y \ Y=3/4 cycle
27929 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
27931 \ ******************************\
27932 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27933 \ ******************************\
27934 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27935 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
27936 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27937 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27938 SUB #1,W \ decrement count loop
27939 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
27940 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27941 0<> WHILE \ ----> out of loop ----+
27942 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27944 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
27945 CMP Y,X \ 1 | cycle time out of bound ?
27946 U>= IF \ 2 ^ | yes:
27947 BIC #$30,&RC5_TIM_CTL \ | | stop timer
27948 GOTO BW1 \ | | quit on truncated RC5 message
27950 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
27952 REPEAT \ ----> loop back --+ | with X = new RC5_period value
27953 \ ******************************\ |
27954 \ RC5_SampleEndOf: \ <---------------------+
27955 \ ******************************\
27956 BIC #$30,&RC5_TIM_CTL \ stop timer
27957 \ ******************************\
27958 \ RC5_ComputeNewRC5word \
27959 \ ******************************\
27960 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
27961 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27962 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27963 \ ******************************\
27964 \ RC5_ComputeC6bit \
27965 \ ******************************\
27966 BIT #BIT14,T \ test /C6 bit in T
27967 0= IF BIS #BIT6,X \ set C6 bit in X
27968 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27969 \ ******************************\
27970 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27971 \ ******************************\
27972 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27973 \ ******************************\
27974 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27975 XOR @RSP,T \ (new XOR old) Toggle bits
27976 BIT #UF10,T \ repeated RC5_command ?
27977 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
27978 XOR #UF10,0(RSP) \ 5 toggle bit memory
27979 \ ******************************\
27980 \ Display IR_RC5 code \
27981 \ ******************************\
27982 SUB #8,PSP \ TOS -- x x x x TOS
27983 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27984 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27985 MOV #$10,&BASEADR \ set hexadecimal base
27986 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27987 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27988 LO2HI \ switch from assembler to FORTH
27989 LCD_CLEAR \ set LCD cursor at home
27990 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27991 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27992 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27993 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27994 HI2LO \ -- switch from FORTH to assembler
27995 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27996 MOV @PSP+,TOS \ -- TOS
28000 \ ------------------------------\
28002 \ ------------------------------\
28004 \ ... \ insert here your background task
28007 CALL &RXON \ comment this line to disable TERMINAL
28009 \ ******************************\
28010 \ here start all interrupts \
28011 \ ******************************\
28012 \ here return all interrupts \
28013 \ ******************************\
28017 \ ------------------------------\
28018 CODE STOP \ stops multitasking, must to be used before downloading app
28019 \ ------------------------------\
28020 \ restore default action of primary DEFERred word SLEEP (assembly version)
28021 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
28022 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28023 MOV X,-2(X) \ restore the default background
28024 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28025 ['] WARM >BODY IS WARM \ restore the default WARM
28027 ." RC5toLCD is removed. type START to restart"
28028 COLD \ performs reset to reset all interrupt vectors.
28031 \ ------------------------------\
28032 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
28033 \ ------------------------------\
28034 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28035 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28036 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28037 \ -- \ID input divider \ 10 = /4
28038 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28039 \ - \TBCLR TimerB Clear
28042 \ -------------------------------\
28043 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28044 \ -- \CM Capture Mode
28049 \ --- \OUTMOD \ 011 = set/reset
28055 \ -------------------------------\
28057 \ -------------------------------\
28059 \ ------------------------------\
28060 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28061 \ ------------------------------\
28062 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28063 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28064 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28065 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28067 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28068 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28070 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28071 \ ------------------------------\
28072 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28073 \ ------------------------------\
28074 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28075 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28076 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28077 \ ------------------------------\
28078 BIS.B #LCDVo,&LCDVo_DIR \
28079 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28080 \ ------------------------------\
28081 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28082 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28083 \ ------------------------------\
28084 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28085 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28086 \ ******************************\
28088 \ ******************************\
28089 BIS.B #RC5,&IR_IE \ enable RC5_Int
28090 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28091 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28092 \ ******************************\
28093 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
28094 \ ******************************\
28095 \ %01 0001 0100 \ TAxCTL
28096 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
28097 \ -- \ ID divided by 1
28098 \ -- \ MC MODE = up to TAxCCRn
28099 \ - \ TACLR clear timer count
28102 \ ------------------------------\
28103 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
28104 \ ------------------------------\
28106 \ --- \ TAIDEX pre divisor
28107 \ ------------------------------\
28108 \ %0000 0000 0000 0101 \ TAxCCR0
28109 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
28110 \ ------------------------------\
28111 \ %0000 0000 0001 0000 \ TAxCCTL0
28112 \ - \ CAP capture/compare mode = compare
28115 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
28116 \ ------------------------------\
28117 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
28118 \ ------------------------------\
28119 \ define LPM mode for ACCEPT \
28120 \ ------------------------------\
28121 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28122 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28123 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28124 \ ------------------------------\
28126 \ ------------------------------\
28127 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
28128 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
28129 \ ------------------------------\
28130 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
28131 \ ------------------------------\
28132 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
28133 \ CMP #2,Y \ Power_ON event
28134 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
28136 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
28138 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
28140 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
28142 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
28143 \ ------------------------------\
28145 \ ------------------------------\
28147 \ ------------------------------\
28148 #1000 20_US \ 1- wait 20 ms
28149 %011 TOP_LCD \ 2- send DB5=DB4=1
28150 #205 20_US \ 3- wait 4,1 ms
28151 %011 TOP_LCD \ 4- send again DB5=DB4=1
28152 #5 20_US \ 5- wait 0,1 ms
28153 %011 TOP_LCD \ 6- send again again DB5=DB4=1
28154 #2 20_US \ wait 40 us = LCD cycle
28155 %010 TOP_LCD \ 7- send DB5=1 DB4=0
28156 #2 20_US \ wait 40 us = LCD cycle
28157 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28158 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28159 LCD_CLEAR \ 10- "LCD_Clear"
28160 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28161 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28162 LCD_CLEAR \ 10- "LCD_Clear"
28163 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28164 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28165 CR ." I love you" \ display message on LCD
28166 ['] CR >BODY IS CR \ CR executes its default value
28167 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
28168 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
28169 ABORT \ ...and end APP_INIT with ABORT, no return.
28172 \ ------------------------------\
28173 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
28174 \ ------------------------------\
28175 MOV #SLEEP,X \ replace default background process
28176 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
28177 MOV #WARM,X \ replace default WARM
28178 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
28179 MOV X,PC \ then execute it
28182 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
28186 CODE 20_US \ n -- n * 20 us
28187 BEGIN \ here we presume that LCD_TIM_IFG = 1...
28189 BIT #1,&LCD_TIM_CTL \ 3
28190 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
28191 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
28193 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
28198 CODE TOP_LCD \ LCD Sample
28199 \ \ if write : %xxxxWWWW --
28200 \ \ if read : -- %0000RRRR
28201 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28202 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28203 0= IF \ write LCD bits pattern
28204 AND.B #LCD_DB,TOS \
28205 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28206 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28209 THEN \ read LCD bits pattern
28212 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28213 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28214 AND.B #LCD_DB,TOS \
28218 CODE LCD_WRC \ char -- Write Char
28219 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28221 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28222 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28223 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28224 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28225 COLON \ high level word starts here
28226 TOP_LCD 2 20_US \ write high nibble first
28230 CODE LCD_WRF \ func -- Write Fonction
28231 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28235 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
28236 : LCD_HOME $02 LCD_WRF 100 20_us ;
28238 \ [UNDEFINED] OR [IF]
28240 \ \ https://forth-standard.org/standard/core/OR
28241 \ \ C OR x1 x2 -- x3 logical OR
28249 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
28250 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
28251 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
28252 \ : LCD_FN_SET $20 OR LCD_WrF ;
28253 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
28254 \ : LCD_GOTO $80 OR LCD_WrF ;
28257 \ CODE LCD_RDS \ -- status Read Status
28258 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28259 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28260 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28261 \ COLON \ starts a FORTH word
28262 \ TOP_LCD 2 20_us \ -- %0000HHHH
28263 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28264 \ HI2LO \ switch from FORTH to assembler
28265 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28266 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28267 \ MOV @RSP+,IP \ restore IP saved by COLON
28271 \ CODE LCD_RDC \ -- char Read Char
28272 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28277 \ ******************************\
28278 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28279 \ ******************************\
28280 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28281 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
28282 BIT.B #SW2,&SW2_IN \ test switch S2
28283 0= IF \ case of switch S2 pressed
28284 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28286 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
28289 BIT.B #SW1,&SW1_IN \ test switch S1 input
28290 0= IF \ case of Switch S1 pressed
28291 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28293 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28297 BW1 \ from quit on truncated RC5 message, repeated RC5 command
28301 \ ******************************\
28302 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28303 \ ******************************\
28304 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28305 \ ******************************\
28306 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28307 \ \ SMclock = 8|16|24 MHz
28308 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28309 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28310 \ \ SR(9)=new Toggle bit memory (ADD on)
28311 \ ******************************\
28312 \ RC5_FirstStartBitHalfCycle: \
28313 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28314 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28315 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
28316 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
28318 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
28319 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
28321 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
28322 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
28324 MOV #1778,X \ RC5_Period * 1us
28325 MOV #14,W \ count of loop
28327 \ ******************************\
28328 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
28329 \ ******************************\ |
28330 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28331 \ RC5_Compute_3/4_Period: \ |
28332 RRUM #1,X \ X=1/2 cycle |
28335 ADD X,Y \ Y=3/4 cycle
28336 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
28338 \ ******************************\
28339 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28340 \ ******************************\
28341 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28342 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
28343 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28344 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28345 SUB #1,W \ decrement count loop
28346 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
28347 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28348 0<> WHILE \ ----> out of loop ----+
28349 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28351 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
28352 CMP Y,X \ 1 | cycle time out of bound ?
28353 U>= IF \ 2 ^ | yes:
28354 BIC #$30,&RC5_TIM_CTL \ | | stop timer
28355 GOTO BW1 \ | | quit on truncated RC5 message
28357 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
28359 REPEAT \ ----> loop back --+ | with X = new RC5_period value
28360 \ ******************************\ |
28361 \ RC5_SampleEndOf: \ <---------------------+
28362 \ ******************************\
28363 BIC #$30,&RC5_TIM_CTL \ stop timer
28364 \ ******************************\
28365 \ RC5_ComputeNewRC5word \
28366 \ ******************************\
28367 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
28368 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
28369 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
28370 \ ******************************\
28371 \ RC5_ComputeC6bit \
28372 \ ******************************\
28373 BIT #BIT14,T \ test /C6 bit in T
28374 0= IF BIS #BIT6,X \ set C6 bit in X
28375 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
28376 \ ******************************\
28377 \ RC5_CommandByteIsDone \ -- BASE RC5_code
28378 \ ******************************\
28379 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28380 \ ******************************\
28381 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
28382 XOR @RSP,T \ (new XOR old) Toggle bits
28383 BIT #UF10,T \ repeated RC5_command ?
28384 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
28385 XOR #UF10,0(RSP) \ 5 toggle bit memory
28386 \ ******************************\
28387 \ Display IR_RC5 code \
28388 \ ******************************\
28389 SUB #8,PSP \ TOS -- x x x x TOS
28390 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
28391 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
28392 MOV #$10,&BASEADR \ set hexadecimal base
28393 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
28394 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
28395 LO2HI \ switch from assembler to FORTH
28396 LCD_CLEAR \ set LCD cursor at home
28397 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
28398 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
28399 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
28400 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
28401 HI2LO \ -- switch from FORTH to assembler
28402 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
28403 MOV @PSP+,TOS \ -- TOS
28407 \ ------------------------------\
28409 \ ------------------------------\
28411 \ ... \ insert here your background task
28414 CALL &RXON \ comment this line to disable TERMINAL
28416 \ ******************************\
28417 \ here start all interrupts \
28418 \ ******************************\
28419 \ here return all interrupts \
28420 \ ******************************\
28424 \ ------------------------------\
28425 CODE STOP \ stops multitasking, must to be used before downloading app
28426 \ ------------------------------\
28427 \ restore default action of primary DEFERred word SLEEP (assembly version)
28428 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
28429 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28430 MOV X,-2(X) \ restore the default background
28431 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28432 ['] WARM >BODY IS WARM \ restore the default WARM
28434 ." RC5toLCD is removed. type START to restart"
28435 COLD \ performs reset to reset all interrupt vectors.
28438 \ ------------------------------\
28439 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
28440 \ ------------------------------\
28441 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28442 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28443 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28444 \ -- \ID input divider \ 10 = /4
28445 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28446 \ - \TBCLR TimerB Clear
28449 \ -------------------------------\
28450 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28451 \ -- \CM Capture Mode
28456 \ --- \OUTMOD \ 011 = set/reset
28462 \ -------------------------------\
28464 \ -------------------------------\
28466 \ ------------------------------\
28467 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28468 \ ------------------------------\
28469 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28470 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28471 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28472 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28474 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28475 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28477 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28478 \ ------------------------------\
28479 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28480 \ ------------------------------\
28481 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28482 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28483 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28484 \ ------------------------------\
28485 BIS.B #LCDVo,&LCDVo_DIR \
28486 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28487 \ ------------------------------\
28488 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28489 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28490 \ ------------------------------\
28491 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28492 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28493 \ ******************************\
28495 \ ******************************\
28496 BIS.B #RC5,&IR_IE \ enable RC5_Int
28497 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28498 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28499 \ ******************************\
28500 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
28501 \ ******************************\
28502 \ %01 0001 0100 \ TAxCTL
28503 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
28504 \ -- \ ID divided by 1
28505 \ -- \ MC MODE = up to TAxCCRn
28506 \ - \ TACLR clear timer count
28509 \ ------------------------------\
28510 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
28511 \ ------------------------------\
28513 \ --- \ TAIDEX pre divisor
28514 \ ------------------------------\
28515 \ %0000 0000 0000 0101 \ TAxCCR0
28516 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
28517 \ ------------------------------\
28518 \ %0000 0000 0001 0000 \ TAxCCTL0
28519 \ - \ CAP capture/compare mode = compare
28522 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
28523 \ ------------------------------\
28524 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
28525 \ ------------------------------\
28526 \ define LPM mode for ACCEPT \
28527 \ ------------------------------\
28528 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28529 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28530 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28531 \ ------------------------------\
28533 \ ------------------------------\
28534 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
28535 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
28536 \ ------------------------------\
28537 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
28538 \ ------------------------------\
28539 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
28540 \ CMP #2,Y \ Power_ON event
28541 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
28543 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
28545 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
28547 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
28549 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
28550 \ ------------------------------\
28552 \ ------------------------------\
28554 \ ------------------------------\
28555 #1000 20_US \ 1- wait 20 ms
28556 %011 TOP_LCD \ 2- send DB5=DB4=1
28557 #205 20_US \ 3- wait 4,1 ms
28558 %011 TOP_LCD \ 4- send again DB5=DB4=1
28559 #5 20_US \ 5- wait 0,1 ms
28560 %011 TOP_LCD \ 6- send again again DB5=DB4=1
28561 #2 20_US \ wait 40 us = LCD cycle
28562 %010 TOP_LCD \ 7- send DB5=1 DB4=0
28563 #2 20_US \ wait 40 us = LCD cycle
28564 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28565 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28566 LCD_CLEAR \ 10- "LCD_Clear"
28567 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28568 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28569 LCD_CLEAR \ 10- "LCD_Clear"
28570 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28571 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28572 CR ." I love you" \ display message on LCD
28573 ['] CR >BODY IS CR \ CR executes its default value
28574 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
28575 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
28576 ABORT \ ...and end APP_INIT with ABORT, no return.
28579 \ ------------------------------\
28580 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
28581 \ ------------------------------\
28582 MOV #SLEEP,X \ replace default background process
28583 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
28584 MOV #WARM,X \ replace default WARM
28585 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
28586 MOV X,PC \ then execute it
28589 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
28593 CODE 20_US \ n -- n * 20 us
28594 BEGIN \ here we presume that LCD_TIM_IFG = 1...
28596 BIT #1,&LCD_TIM_CTL \ 3
28597 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
28598 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
28600 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
28605 CODE TOP_LCD \ LCD Sample
28606 \ \ if write : %xxxxWWWW --
28607 \ \ if read : -- %0000RRRR
28608 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28609 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28610 0= IF \ write LCD bits pattern
28611 AND.B #LCD_DB,TOS \
28612 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28613 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28616 THEN \ read LCD bits pattern
28619 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28620 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28621 AND.B #LCD_DB,TOS \
28625 CODE LCD_WRC \ char -- Write Char
28626 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28628 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28629 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28630 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28631 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28632 COLON \ high level word starts here
28633 TOP_LCD 2 20_US \ write high nibble first
28637 CODE LCD_WRF \ func -- Write Fonction
28638 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28642 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
28643 : LCD_HOME $02 LCD_WRF 100 20_us ;
28645 \ [UNDEFINED] OR [IF]
28647 \ \ https://forth-standard.org/standard/core/OR
28648 \ \ C OR x1 x2 -- x3 logical OR
28656 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
28657 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
28658 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
28659 \ : LCD_FN_SET $20 OR LCD_WrF ;
28660 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
28661 \ : LCD_GOTO $80 OR LCD_WrF ;
28664 \ CODE LCD_RDS \ -- status Read Status
28665 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28666 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28667 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28668 \ COLON \ starts a FORTH word
28669 \ TOP_LCD 2 20_us \ -- %0000HHHH
28670 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28671 \ HI2LO \ switch from FORTH to assembler
28672 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28673 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28674 \ MOV @RSP+,IP \ restore IP saved by COLON
28678 \ CODE LCD_RDC \ -- char Read Char
28679 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28684 \ ******************************\
28685 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28686 \ ******************************\
28687 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28688 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
28689 BIT.B #SW2,&SW2_IN \ test switch S2
28690 0= IF \ case of switch S2 pressed
28691 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28693 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
28696 BIT.B #SW1,&SW1_IN \ test switch S1 input
28697 0= IF \ case of Switch S1 pressed
28698 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28700 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28704 BW1 \ from quit on truncated RC5 message, repeated RC5 command
28708 \ ******************************\
28709 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28710 \ ******************************\
28711 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28712 \ ******************************\
28713 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28714 \ \ SMclock = 8|16|24 MHz
28715 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28716 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28717 \ \ SR(9)=new Toggle bit memory (ADD on)
28718 \ ******************************\
28719 \ RC5_FirstStartBitHalfCycle: \
28720 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28721 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28722 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
28723 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
28725 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
28726 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
28728 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
28729 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
28731 MOV #1778,X \ RC5_Period * 1us
28732 MOV #14,W \ count of loop
28734 \ ******************************\
28735 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
28736 \ ******************************\ |
28737 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28738 \ RC5_Compute_3/4_Period: \ |
28739 RRUM #1,X \ X=1/2 cycle |
28742 ADD X,Y \ Y=3/4 cycle
28743 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
28745 \ ******************************\
28746 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28747 \ ******************************\
28748 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28749 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
28750 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28751 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28752 SUB #1,W \ decrement count loop
28753 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
28754 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28755 0<> WHILE \ ----> out of loop ----+
28756 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28758 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
28759 CMP Y,X \ 1 | cycle time out of bound ?
28760 U>= IF \ 2 ^ | yes:
28761 BIC #$30,&RC5_TIM_CTL \ | | stop timer
28762 GOTO BW1 \ | | quit on truncated RC5 message
28764 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
28766 REPEAT \ ----> loop back --+ | with X = new RC5_period value
28767 \ ******************************\ |
28768 \ RC5_SampleEndOf: \ <---------------------+
28769 \ ******************************\
28770 BIC #$30,&RC5_TIM_CTL \ stop timer
28771 \ ******************************\
28772 \ RC5_ComputeNewRC5word \
28773 \ ******************************\
28774 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
28775 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
28776 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
28777 \ ******************************\
28778 \ RC5_ComputeC6bit \
28779 \ ******************************\
28780 BIT #BIT14,T \ test /C6 bit in T
28781 0= IF BIS #BIT6,X \ set C6 bit in X
28782 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
28783 \ ******************************\
28784 \ RC5_CommandByteIsDone \ -- BASE RC5_code
28785 \ ******************************\
28786 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28787 \ ******************************\
28788 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
28789 XOR @RSP,T \ (new XOR old) Toggle bits
28790 BIT #UF10,T \ repeated RC5_command ?
28791 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
28792 XOR #UF10,0(RSP) \ 5 toggle bit memory
28793 \ ******************************\
28794 \ Display IR_RC5 code \
28795 \ ******************************\
28796 SUB #8,PSP \ TOS -- x x x x TOS
28797 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
28798 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
28799 MOV #$10,&BASEADR \ set hexadecimal base
28800 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
28801 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
28802 LO2HI \ switch from assembler to FORTH
28803 LCD_CLEAR \ set LCD cursor at home
28804 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
28805 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
28806 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
28807 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
28808 HI2LO \ -- switch from FORTH to assembler
28809 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
28810 MOV @PSP+,TOS \ -- TOS
28814 \ ------------------------------\
28816 \ ------------------------------\
28818 \ ... \ insert here your background task
28821 CALL &RXON \ comment this line to disable TERMINAL
28823 \ ******************************\
28824 \ here start all interrupts \
28825 \ ******************************\
28826 \ here return all interrupts \
28827 \ ******************************\
28831 \ ------------------------------\
28832 CODE STOP \ stops multitasking, must to be used before downloading app
28833 \ ------------------------------\
28834 \ restore default action of primary DEFERred word SLEEP (assembly version)
28835 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
28836 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28837 MOV X,-2(X) \ restore the default background
28838 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28839 ['] WARM >BODY IS WARM \ restore the default WARM
28841 ." RC5toLCD is removed. type START to restart"
28842 COLD \ performs reset to reset all interrupt vectors.
28845 \ ------------------------------\
28846 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
28847 \ ------------------------------\
28848 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28849 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28850 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28851 \ -- \ID input divider \ 10 = /4
28852 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28853 \ - \TBCLR TimerB Clear
28856 \ -------------------------------\
28857 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28858 \ -- \CM Capture Mode
28863 \ --- \OUTMOD \ 011 = set/reset
28869 \ -------------------------------\
28871 \ -------------------------------\
28873 \ ------------------------------\
28874 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28875 \ ------------------------------\
28876 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28877 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28878 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28879 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28881 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28882 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28884 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28885 \ ------------------------------\
28886 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28887 \ ------------------------------\
28888 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28889 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28890 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28891 \ ------------------------------\
28892 BIS.B #LCDVo,&LCDVo_DIR \
28893 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28894 \ ------------------------------\
28895 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28896 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28897 \ ------------------------------\
28898 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28899 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28900 \ ******************************\
28902 \ ******************************\
28903 BIS.B #RC5,&IR_IE \ enable RC5_Int
28904 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28905 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28906 \ ******************************\
28907 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
28908 \ ******************************\
28909 \ %01 0001 0100 \ TAxCTL
28910 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
28911 \ -- \ ID divided by 1
28912 \ -- \ MC MODE = up to TAxCCRn
28913 \ - \ TACLR clear timer count
28916 \ ------------------------------\
28917 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
28918 \ ------------------------------\
28920 \ --- \ TAIDEX pre divisor
28921 \ ------------------------------\
28922 \ %0000 0000 0000 0101 \ TAxCCR0
28923 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
28924 \ ------------------------------\
28925 \ %0000 0000 0001 0000 \ TAxCCTL0
28926 \ - \ CAP capture/compare mode = compare
28929 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
28930 \ ------------------------------\
28931 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
28932 \ ------------------------------\
28933 \ define LPM mode for ACCEPT \
28934 \ ------------------------------\
28935 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28936 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28937 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28938 \ ------------------------------\
28940 \ ------------------------------\
28941 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
28942 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
28943 \ ------------------------------\
28944 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
28945 \ ------------------------------\
28946 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
28947 \ CMP #2,Y \ Power_ON event
28948 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
28950 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
28952 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
28954 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
28956 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
28957 \ ------------------------------\
28959 \ ------------------------------\
28961 \ ------------------------------\
28962 #1000 20_US \ 1- wait 20 ms
28963 %011 TOP_LCD \ 2- send DB5=DB4=1
28964 #205 20_US \ 3- wait 4,1 ms
28965 %011 TOP_LCD \ 4- send again DB5=DB4=1
28966 #5 20_US \ 5- wait 0,1 ms
28967 %011 TOP_LCD \ 6- send again again DB5=DB4=1
28968 #2 20_US \ wait 40 us = LCD cycle
28969 %010 TOP_LCD \ 7- send DB5=1 DB4=0
28970 #2 20_US \ wait 40 us = LCD cycle
28971 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28972 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28973 LCD_CLEAR \ 10- "LCD_Clear"
28974 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28975 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28976 LCD_CLEAR \ 10- "LCD_Clear"
28977 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28978 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28979 CR ." I love you" \ display message on LCD
28980 ['] CR >BODY IS CR \ CR executes its default value
28981 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
28982 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
28983 ABORT \ ...and end APP_INIT with ABORT, no return.
28986 \ ------------------------------\
28987 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
28988 \ ------------------------------\
28989 MOV #SLEEP,X \ replace default background process
28990 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
28991 MOV #WARM,X \ replace default WARM
28992 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
28993 MOV X,PC \ then execute it
28996 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29000 CODE 20_US \ n -- n * 20 us
29001 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29003 BIT #1,&LCD_TIM_CTL \ 3
29004 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29005 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29007 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29012 CODE TOP_LCD \ LCD Sample
29013 \ \ if write : %xxxxWWWW --
29014 \ \ if read : -- %0000RRRR
29015 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29016 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29017 0= IF \ write LCD bits pattern
29018 AND.B #LCD_DB,TOS \
29019 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29020 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29023 THEN \ read LCD bits pattern
29026 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29027 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29028 AND.B #LCD_DB,TOS \
29032 CODE LCD_WRC \ char -- Write Char
29033 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29035 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29036 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29037 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29038 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29039 COLON \ high level word starts here
29040 TOP_LCD 2 20_US \ write high nibble first
29044 CODE LCD_WRF \ func -- Write Fonction
29045 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29049 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29050 : LCD_HOME $02 LCD_WRF 100 20_us ;
29052 \ [UNDEFINED] OR [IF]
29054 \ \ https://forth-standard.org/standard/core/OR
29055 \ \ C OR x1 x2 -- x3 logical OR
29063 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29064 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29065 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29066 \ : LCD_FN_SET $20 OR LCD_WrF ;
29067 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29068 \ : LCD_GOTO $80 OR LCD_WrF ;
29071 \ CODE LCD_RDS \ -- status Read Status
29072 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29073 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29074 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29075 \ COLON \ starts a FORTH word
29076 \ TOP_LCD 2 20_us \ -- %0000HHHH
29077 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29078 \ HI2LO \ switch from FORTH to assembler
29079 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29080 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29081 \ MOV @RSP+,IP \ restore IP saved by COLON
29085 \ CODE LCD_RDC \ -- char Read Char
29086 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29091 \ ******************************\
29092 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29093 \ ******************************\
29094 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29095 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29096 BIT.B #SW2,&SW2_IN \ test switch S2
29097 0= IF \ case of switch S2 pressed
29098 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29100 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
29103 BIT.B #SW1,&SW1_IN \ test switch S1 input
29104 0= IF \ case of Switch S1 pressed
29105 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29107 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29111 BW1 \ from quit on truncated RC5 message, repeated RC5 command
29115 \ ******************************\
29116 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29117 \ ******************************\
29118 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29119 \ ******************************\
29120 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29121 \ \ SMclock = 8|16|24 MHz
29122 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29123 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29124 \ \ SR(9)=new Toggle bit memory (ADD on)
29125 \ ******************************\
29126 \ RC5_FirstStartBitHalfCycle: \
29127 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29128 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29129 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
29130 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
29132 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
29133 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
29135 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
29136 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
29138 MOV #1778,X \ RC5_Period * 1us
29139 MOV #14,W \ count of loop
29141 \ ******************************\
29142 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
29143 \ ******************************\ |
29144 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29145 \ RC5_Compute_3/4_Period: \ |
29146 RRUM #1,X \ X=1/2 cycle |
29149 ADD X,Y \ Y=3/4 cycle
29150 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
29152 \ ******************************\
29153 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29154 \ ******************************\
29155 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29156 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
29157 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29158 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29159 SUB #1,W \ decrement count loop
29160 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
29161 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29162 0<> WHILE \ ----> out of loop ----+
29163 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29165 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
29166 CMP Y,X \ 1 | cycle time out of bound ?
29167 U>= IF \ 2 ^ | yes:
29168 BIC #$30,&RC5_TIM_CTL \ | | stop timer
29169 GOTO BW1 \ | | quit on truncated RC5 message
29171 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
29173 REPEAT \ ----> loop back --+ | with X = new RC5_period value
29174 \ ******************************\ |
29175 \ RC5_SampleEndOf: \ <---------------------+
29176 \ ******************************\
29177 BIC #$30,&RC5_TIM_CTL \ stop timer
29178 \ ******************************\
29179 \ RC5_ComputeNewRC5word \
29180 \ ******************************\
29181 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
29182 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
29183 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
29184 \ ******************************\
29185 \ RC5_ComputeC6bit \
29186 \ ******************************\
29187 BIT #BIT14,T \ test /C6 bit in T
29188 0= IF BIS #BIT6,X \ set C6 bit in X
29189 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
29190 \ ******************************\
29191 \ RC5_CommandByteIsDone \ -- BASE RC5_code
29192 \ ******************************\
29193 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29194 \ ******************************\
29195 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
29196 XOR @RSP,T \ (new XOR old) Toggle bits
29197 BIT #UF10,T \ repeated RC5_command ?
29198 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
29199 XOR #UF10,0(RSP) \ 5 toggle bit memory
29200 \ ******************************\
29201 \ Display IR_RC5 code \
29202 \ ******************************\
29203 SUB #8,PSP \ TOS -- x x x x TOS
29204 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
29205 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
29206 MOV #$10,&BASEADR \ set hexadecimal base
29207 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
29208 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
29209 LO2HI \ switch from assembler to FORTH
29210 LCD_CLEAR \ set LCD cursor at home
29211 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
29212 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
29213 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
29214 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
29215 HI2LO \ -- switch from FORTH to assembler
29216 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
29217 MOV @PSP+,TOS \ -- TOS
29221 \ ------------------------------\
29223 \ ------------------------------\
29225 \ ... \ insert here your background task
29228 CALL &RXON \ comment this line to disable TERMINAL
29230 \ ******************************\
29231 \ here start all interrupts \
29232 \ ******************************\
29233 \ here return all interrupts \
29234 \ ******************************\
29238 \ ------------------------------\
29239 CODE STOP \ stops multitasking, must to be used before downloading app
29240 \ ------------------------------\
29241 \ restore default action of primary DEFERred word SLEEP (assembly version)
29242 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
29243 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
29244 MOV X,-2(X) \ restore the default background
29245 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
29246 ['] WARM >BODY IS WARM \ restore the default WARM
29248 ." RC5toLCD is removed. type START to restart"
29249 COLD \ performs reset to reset all interrupt vectors.
29252 \ ------------------------------\
29253 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
29254 \ ------------------------------\
29255 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
29256 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29257 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29258 \ -- \ID input divider \ 10 = /4
29259 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
29260 \ - \TBCLR TimerB Clear
29263 \ -------------------------------\
29264 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29265 \ -- \CM Capture Mode
29270 \ --- \OUTMOD \ 011 = set/reset
29276 \ -------------------------------\
29278 \ -------------------------------\
29280 \ ------------------------------\
29281 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
29282 \ ------------------------------\
29283 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
29284 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
29285 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
29286 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
29288 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
29289 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
29291 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
29292 \ ------------------------------\
29293 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
29294 \ ------------------------------\
29295 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
29296 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
29297 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29298 \ ------------------------------\
29299 BIS.B #LCDVo,&LCDVo_DIR \
29300 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
29301 \ ------------------------------\
29302 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29303 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29304 \ ------------------------------\
29305 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29306 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29307 \ ******************************\
29309 \ ******************************\
29310 BIS.B #RC5,&IR_IE \ enable RC5_Int
29311 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29312 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29313 \ ******************************\
29314 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29315 \ ******************************\
29316 \ %01 0001 0100 \ TAxCTL
29317 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
29318 \ -- \ ID divided by 1
29319 \ -- \ MC MODE = up to TAxCCRn
29320 \ - \ TACLR clear timer count
29323 \ ------------------------------\
29324 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
29325 \ ------------------------------\
29327 \ --- \ TAIDEX pre divisor
29328 \ ------------------------------\
29329 \ %0000 0000 0000 0101 \ TAxCCR0
29330 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29331 \ ------------------------------\
29332 \ %0000 0000 0001 0000 \ TAxCCTL0
29333 \ - \ CAP capture/compare mode = compare
29336 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
29337 \ ------------------------------\
29338 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29339 \ ------------------------------\
29340 \ define LPM mode for ACCEPT \
29341 \ ------------------------------\
29342 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29343 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29344 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29345 \ ------------------------------\
29347 \ ------------------------------\
29348 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
29349 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
29350 \ ------------------------------\
29351 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
29352 \ ------------------------------\
29353 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
29354 \ CMP #2,Y \ Power_ON event
29355 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
29357 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
29359 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
29361 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
29363 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
29364 \ ------------------------------\
29366 \ ------------------------------\
29368 \ ------------------------------\
29369 #1000 20_US \ 1- wait 20 ms
29370 %011 TOP_LCD \ 2- send DB5=DB4=1
29371 #205 20_US \ 3- wait 4,1 ms
29372 %011 TOP_LCD \ 4- send again DB5=DB4=1
29373 #5 20_US \ 5- wait 0,1 ms
29374 %011 TOP_LCD \ 6- send again again DB5=DB4=1
29375 #2 20_US \ wait 40 us = LCD cycle
29376 %010 TOP_LCD \ 7- send DB5=1 DB4=0
29377 #2 20_US \ wait 40 us = LCD cycle
29378 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29379 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29380 LCD_CLEAR \ 10- "LCD_Clear"
29381 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29382 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29383 LCD_CLEAR \ 10- "LCD_Clear"
29384 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29385 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29386 CR ." I love you" \ display message on LCD
29387 ['] CR >BODY IS CR \ CR executes its default value
29388 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
29389 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29390 ABORT \ ...and end APP_INIT with ABORT, no return.
29393 \ ------------------------------\
29394 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
29395 \ ------------------------------\
29396 MOV #SLEEP,X \ replace default background process
29397 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
29398 MOV #WARM,X \ replace default WARM
29399 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
29400 MOV X,PC \ then execute it
29403 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29407 CODE 20_US \ n -- n * 20 us
29408 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29410 BIT #1,&LCD_TIM_CTL \ 3
29411 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29412 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29414 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29419 CODE TOP_LCD \ LCD Sample
29420 \ \ if write : %xxxxWWWW --
29421 \ \ if read : -- %0000RRRR
29422 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29423 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29424 0= IF \ write LCD bits pattern
29425 AND.B #LCD_DB,TOS \
29426 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29427 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29430 THEN \ read LCD bits pattern
29433 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29434 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29435 AND.B #LCD_DB,TOS \
29439 CODE LCD_WRC \ char -- Write Char
29440 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29442 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29443 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29444 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29445 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29446 COLON \ high level word starts here
29447 TOP_LCD 2 20_US \ write high nibble first
29451 CODE LCD_WRF \ func -- Write Fonction
29452 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29456 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29457 : LCD_HOME $02 LCD_WRF 100 20_us ;
29459 \ [UNDEFINED] OR [IF]
29461 \ \ https://forth-standard.org/standard/core/OR
29462 \ \ C OR x1 x2 -- x3 logical OR
29470 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29471 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29472 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29473 \ : LCD_FN_SET $20 OR LCD_WrF ;
29474 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29475 \ : LCD_GOTO $80 OR LCD_WrF ;
29478 \ CODE LCD_RDS \ -- status Read Status
29479 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29480 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29481 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29482 \ COLON \ starts a FORTH word
29483 \ TOP_LCD 2 20_us \ -- %0000HHHH
29484 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29485 \ HI2LO \ switch from FORTH to assembler
29486 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29487 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29488 \ MOV @RSP+,IP \ restore IP saved by COLON
29492 \ CODE LCD_RDC \ -- char Read Char
29493 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29498 \ ******************************\
29499 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29500 \ ******************************\
29501 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29502 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29503 BIT.B #SW2,&SW2_IN \ test switch S2
29504 0= IF \ case of switch S2 pressed
29505 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29507 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
29510 BIT.B #SW1,&SW1_IN \ test switch S1 input
29511 0= IF \ case of Switch S1 pressed
29512 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29514 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29518 BW1 \ from quit on truncated RC5 message, repeated RC5 command
29522 \ ******************************\
29523 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29524 \ ******************************\
29525 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29526 \ ******************************\
29527 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29528 \ \ SMclock = 8|16|24 MHz
29529 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29530 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29531 \ \ SR(9)=new Toggle bit memory (ADD on)
29532 \ ******************************\
29533 \ RC5_FirstStartBitHalfCycle: \
29534 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29535 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29536 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
29537 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
29539 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
29540 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
29542 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
29543 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
29545 MOV #1778,X \ RC5_Period * 1us
29546 MOV #14,W \ count of loop
29548 \ ******************************\
29549 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
29550 \ ******************************\ |
29551 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29552 \ RC5_Compute_3/4_Period: \ |
29553 RRUM #1,X \ X=1/2 cycle |
29556 ADD X,Y \ Y=3/4 cycle
29557 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
29559 \ ******************************\
29560 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29561 \ ******************************\
29562 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29563 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
29564 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29565 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29566 SUB #1,W \ decrement count loop
29567 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
29568 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29569 0<> WHILE \ ----> out of loop ----+
29570 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29572 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
29573 CMP Y,X \ 1 | cycle time out of bound ?
29574 U>= IF \ 2 ^ | yes:
29575 BIC #$30,&RC5_TIM_CTL \ | | stop timer
29576 GOTO BW1 \ | | quit on truncated RC5 message
29578 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
29580 REPEAT \ ----> loop back --+ | with X = new RC5_period value
29581 \ ******************************\ |
29582 \ RC5_SampleEndOf: \ <---------------------+
29583 \ ******************************\
29584 BIC #$30,&RC5_TIM_CTL \ stop timer
29585 \ ******************************\
29586 \ RC5_ComputeNewRC5word \
29587 \ ******************************\
29588 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
29589 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
29590 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
29591 \ ******************************\
29592 \ RC5_ComputeC6bit \
29593 \ ******************************\
29594 BIT #BIT14,T \ test /C6 bit in T
29595 0= IF BIS #BIT6,X \ set C6 bit in X
29596 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
29597 \ ******************************\
29598 \ RC5_CommandByteIsDone \ -- BASE RC5_code
29599 \ ******************************\
29600 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29601 \ ******************************\
29602 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
29603 XOR @RSP,T \ (new XOR old) Toggle bits
29604 BIT #UF10,T \ repeated RC5_command ?
29605 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
29606 XOR #UF10,0(RSP) \ 5 toggle bit memory
29607 \ ******************************\
29608 \ Display IR_RC5 code \
29609 \ ******************************\
29610 SUB #8,PSP \ TOS -- x x x x TOS
29611 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
29612 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
29613 MOV #$10,&BASEADR \ set hexadecimal base
29614 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
29615 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
29616 LO2HI \ switch from assembler to FORTH
29617 LCD_CLEAR \ set LCD cursor at home
29618 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
29619 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
29620 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
29621 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
29622 HI2LO \ -- switch from FORTH to assembler
29623 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
29624 MOV @PSP+,TOS \ -- TOS
29628 \ ------------------------------\
29630 \ ------------------------------\
29632 \ ... \ insert here your background task
29635 CALL &RXON \ comment this line to disable TERMINAL
29637 \ ******************************\
29638 \ here start all interrupts \
29639 \ ******************************\
29640 \ here return all interrupts \
29641 \ ******************************\
29645 \ ------------------------------\
29646 CODE STOP \ stops multitasking, must to be used before downloading app
29647 \ ------------------------------\
29648 \ restore default action of primary DEFERred word SLEEP (assembly version)
29649 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
29650 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
29651 MOV X,-2(X) \ restore the default background
29652 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
29653 ['] WARM >BODY IS WARM \ restore the default WARM
29655 ." RC5toLCD is removed. type START to restart"
29656 COLD \ performs reset to reset all interrupt vectors.
29659 \ ------------------------------\
29660 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
29661 \ ------------------------------\
29662 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
29663 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29664 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29665 \ -- \ID input divider \ 10 = /4
29666 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
29667 \ - \TBCLR TimerB Clear
29670 \ -------------------------------\
29671 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29672 \ -- \CM Capture Mode
29677 \ --- \OUTMOD \ 011 = set/reset
29683 \ -------------------------------\
29685 \ -------------------------------\
29687 \ ------------------------------\
29688 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
29689 \ ------------------------------\
29690 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
29691 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
29692 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
29693 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
29695 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
29696 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
29698 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
29699 \ ------------------------------\
29700 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
29701 \ ------------------------------\
29702 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
29703 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
29704 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29705 \ ------------------------------\
29706 BIS.B #LCDVo,&LCDVo_DIR \
29707 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
29708 \ ------------------------------\
29709 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29710 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29711 \ ------------------------------\
29712 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29713 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29714 \ ******************************\
29716 \ ******************************\
29717 BIS.B #RC5,&IR_IE \ enable RC5_Int
29718 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29719 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29720 \ ******************************\
29721 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29722 \ ******************************\
29723 \ %01 0001 0100 \ TAxCTL
29724 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
29725 \ -- \ ID divided by 1
29726 \ -- \ MC MODE = up to TAxCCRn
29727 \ - \ TACLR clear timer count
29730 \ ------------------------------\
29731 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
29732 \ ------------------------------\
29734 \ --- \ TAIDEX pre divisor
29735 \ ------------------------------\
29736 \ %0000 0000 0000 0101 \ TAxCCR0
29737 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29738 \ ------------------------------\
29739 \ %0000 0000 0001 0000 \ TAxCCTL0
29740 \ - \ CAP capture/compare mode = compare
29743 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
29744 \ ------------------------------\
29745 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29746 \ ------------------------------\
29747 \ define LPM mode for ACCEPT \
29748 \ ------------------------------\
29749 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29750 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29751 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29752 \ ------------------------------\
29754 \ ------------------------------\
29755 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
29756 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
29757 \ ------------------------------\
29758 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
29759 \ ------------------------------\
29760 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
29761 \ CMP #2,Y \ Power_ON event
29762 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
29764 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
29766 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
29768 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
29770 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
29771 \ ------------------------------\
29773 \ ------------------------------\
29775 \ ------------------------------\
29776 #1000 20_US \ 1- wait 20 ms
29777 %011 TOP_LCD \ 2- send DB5=DB4=1
29778 #205 20_US \ 3- wait 4,1 ms
29779 %011 TOP_LCD \ 4- send again DB5=DB4=1
29780 #5 20_US \ 5- wait 0,1 ms
29781 %011 TOP_LCD \ 6- send again again DB5=DB4=1
29782 #2 20_US \ wait 40 us = LCD cycle
29783 %010 TOP_LCD \ 7- send DB5=1 DB4=0
29784 #2 20_US \ wait 40 us = LCD cycle
29785 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29786 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29787 LCD_CLEAR \ 10- "LCD_Clear"
29788 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29789 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29790 LCD_CLEAR \ 10- "LCD_Clear"
29791 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29792 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29793 CR ." I love you" \ display message on LCD
29794 ['] CR >BODY IS CR \ CR executes its default value
29795 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
29796 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29797 ABORT \ ...and end APP_INIT with ABORT, no return.
29800 \ ------------------------------\
29801 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
29802 \ ------------------------------\
29803 MOV #SLEEP,X \ replace default background process
29804 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
29805 MOV #WARM,X \ replace default WARM
29806 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
29807 MOV X,PC \ then execute it
29810 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29814 CODE 20_US \ n -- n * 20 us
29815 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29817 BIT #1,&LCD_TIM_CTL \ 3
29818 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29819 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29821 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29826 CODE TOP_LCD \ LCD Sample
29827 \ \ if write : %xxxxWWWW --
29828 \ \ if read : -- %0000RRRR
29829 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29830 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29831 0= IF \ write LCD bits pattern
29832 AND.B #LCD_DB,TOS \
29833 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29834 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29837 THEN \ read LCD bits pattern
29840 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29841 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29842 AND.B #LCD_DB,TOS \
29846 CODE LCD_WRC \ char -- Write Char
29847 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29849 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29850 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29851 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29852 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29853 COLON \ high level word starts here
29854 TOP_LCD 2 20_US \ write high nibble first
29858 CODE LCD_WRF \ func -- Write Fonction
29859 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29863 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29864 : LCD_HOME $02 LCD_WRF 100 20_us ;
29866 \ [UNDEFINED] OR [IF]
29868 \ \ https://forth-standard.org/standard/core/OR
29869 \ \ C OR x1 x2 -- x3 logical OR
29877 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29878 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29879 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29880 \ : LCD_FN_SET $20 OR LCD_WrF ;
29881 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29882 \ : LCD_GOTO $80 OR LCD_WrF ;
29885 \ CODE LCD_RDS \ -- status Read Status
29886 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29887 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29888 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29889 \ COLON \ starts a FORTH word
29890 \ TOP_LCD 2 20_us \ -- %0000HHHH
29891 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29892 \ HI2LO \ switch from FORTH to assembler
29893 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29894 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29895 \ MOV @RSP+,IP \ restore IP saved by COLON
29899 \ CODE LCD_RDC \ -- char Read Char
29900 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29905 \ ******************************\
29906 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29907 \ ******************************\
29908 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29909 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29910 BIT.B #SW2,&SW2_IN \ test switch S2
29911 0= IF \ case of switch S2 pressed
29912 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29914 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
29917 BIT.B #SW1,&SW1_IN \ test switch S1 input
29918 0= IF \ case of Switch S1 pressed
29919 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29921 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29925 BW1 \ from quit on truncated RC5 message, repeated RC5 command
29929 \ ******************************\
29930 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29931 \ ******************************\
29932 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29933 \ ******************************\
29934 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29935 \ \ SMclock = 8|16|24 MHz
29936 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29937 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29938 \ \ SR(9)=new Toggle bit memory (ADD on)
29939 \ ******************************\
29940 \ RC5_FirstStartBitHalfCycle: \
29941 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29942 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29943 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
29944 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
29946 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
29947 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
29949 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
29950 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
29952 MOV #1778,X \ RC5_Period * 1us
29953 MOV #14,W \ count of loop
29955 \ ******************************\
29956 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
29957 \ ******************************\ |
29958 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29959 \ RC5_Compute_3/4_Period: \ |
29960 RRUM #1,X \ X=1/2 cycle |
29963 ADD X,Y \ Y=3/4 cycle
29964 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
29966 \ ******************************\
29967 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29968 \ ******************************\
29969 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29970 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
29971 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29972 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29973 SUB #1,W \ decrement count loop
29974 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
29975 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29976 0<> WHILE \ ----> out of loop ----+
29977 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29979 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
29980 CMP Y,X \ 1 | cycle time out of bound ?
29981 U>= IF \ 2 ^ | yes:
29982 BIC #$30,&RC5_TIM_CTL \ | | stop timer
29983 GOTO BW1 \ | | quit on truncated RC5 message
29985 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
29987 REPEAT \ ----> loop back --+ | with X = new RC5_period value
29988 \ ******************************\ |
29989 \ RC5_SampleEndOf: \ <---------------------+
29990 \ ******************************\
29991 BIC #$30,&RC5_TIM_CTL \ stop timer
29992 \ ******************************\
29993 \ RC5_ComputeNewRC5word \
29994 \ ******************************\
29995 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
29996 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
29997 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
29998 \ ******************************\
29999 \ RC5_ComputeC6bit \
30000 \ ******************************\
30001 BIT #BIT14,T \ test /C6 bit in T
30002 0= IF BIS #BIT6,X \ set C6 bit in X
30003 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
30004 \ ******************************\
30005 \ RC5_CommandByteIsDone \ -- BASE RC5_code
30006 \ ******************************\
30007 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30008 \ ******************************\
30009 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
30010 XOR @RSP,T \ (new XOR old) Toggle bits
30011 BIT #UF10,T \ repeated RC5_command ?
30012 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
30013 XOR #UF10,0(RSP) \ 5 toggle bit memory
30014 \ ******************************\
30015 \ Display IR_RC5 code \
30016 \ ******************************\
30017 SUB #8,PSP \ TOS -- x x x x TOS
30018 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
30019 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
30020 MOV #$10,&BASEADR \ set hexadecimal base
30021 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
30022 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
30023 LO2HI \ switch from assembler to FORTH
30024 LCD_CLEAR \ set LCD cursor at home
30025 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
30026 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
30027 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
30028 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
30029 HI2LO \ -- switch from FORTH to assembler
30030 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
30031 MOV @PSP+,TOS \ -- TOS
30035 \ ------------------------------\
30037 \ ------------------------------\
30039 \ ... \ insert here your background task
30042 CALL &RXON \ comment this line to disable TERMINAL
30044 \ ******************************\
30045 \ here start all interrupts \
30046 \ ******************************\
30047 \ here return all interrupts \
30048 \ ******************************\
30052 \ ------------------------------\
30053 CODE STOP \ stops multitasking, must to be used before downloading app
30054 \ ------------------------------\
30055 \ restore default action of primary DEFERred word SLEEP (assembly version)
30056 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
30057 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30058 MOV X,-2(X) \ restore the default background
30059 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30060 ['] WARM >BODY IS WARM \ restore the default WARM
30062 ." RC5toLCD is removed. type START to restart"
30063 COLD \ performs reset to reset all interrupt vectors.
30066 \ ------------------------------\
30067 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
30068 \ ------------------------------\
30069 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30070 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30071 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30072 \ -- \ID input divider \ 10 = /4
30073 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30074 \ - \TBCLR TimerB Clear
30077 \ -------------------------------\
30078 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30079 \ -- \CM Capture Mode
30084 \ --- \OUTMOD \ 011 = set/reset
30090 \ -------------------------------\
30092 \ -------------------------------\
30094 \ ------------------------------\
30095 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30096 \ ------------------------------\
30097 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30098 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30099 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30100 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30102 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30103 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30105 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30106 \ ------------------------------\
30107 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30108 \ ------------------------------\
30109 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30110 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30111 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30112 \ ------------------------------\
30113 BIS.B #LCDVo,&LCDVo_DIR \
30114 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30115 \ ------------------------------\
30116 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30117 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30118 \ ------------------------------\
30119 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30120 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30121 \ ******************************\
30123 \ ******************************\
30124 BIS.B #RC5,&IR_IE \ enable RC5_Int
30125 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30126 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30127 \ ******************************\
30128 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30129 \ ******************************\
30130 \ %01 0001 0100 \ TAxCTL
30131 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30132 \ -- \ ID divided by 1
30133 \ -- \ MC MODE = up to TAxCCRn
30134 \ - \ TACLR clear timer count
30137 \ ------------------------------\
30138 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30139 \ ------------------------------\
30141 \ --- \ TAIDEX pre divisor
30142 \ ------------------------------\
30143 \ %0000 0000 0000 0101 \ TAxCCR0
30144 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30145 \ ------------------------------\
30146 \ %0000 0000 0001 0000 \ TAxCCTL0
30147 \ - \ CAP capture/compare mode = compare
30150 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30151 \ ------------------------------\
30152 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30153 \ ------------------------------\
30154 \ define LPM mode for ACCEPT \
30155 \ ------------------------------\
30156 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30157 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30158 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30159 \ ------------------------------\
30161 \ ------------------------------\
30162 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
30163 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30164 \ ------------------------------\
30165 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30166 \ ------------------------------\
30167 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
30168 \ CMP #2,Y \ Power_ON event
30169 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30171 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
30173 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30175 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30177 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30178 \ ------------------------------\
30180 \ ------------------------------\
30182 \ ------------------------------\
30183 #1000 20_US \ 1- wait 20 ms
30184 %011 TOP_LCD \ 2- send DB5=DB4=1
30185 #205 20_US \ 3- wait 4,1 ms
30186 %011 TOP_LCD \ 4- send again DB5=DB4=1
30187 #5 20_US \ 5- wait 0,1 ms
30188 %011 TOP_LCD \ 6- send again again DB5=DB4=1
30189 #2 20_US \ wait 40 us = LCD cycle
30190 %010 TOP_LCD \ 7- send DB5=1 DB4=0
30191 #2 20_US \ wait 40 us = LCD cycle
30192 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30193 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30194 LCD_CLEAR \ 10- "LCD_Clear"
30195 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30196 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30197 LCD_CLEAR \ 10- "LCD_Clear"
30198 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30199 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30200 CR ." I love you" \ display message on LCD
30201 ['] CR >BODY IS CR \ CR executes its default value
30202 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
30203 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30204 ABORT \ ...and end APP_INIT with ABORT, no return.
30207 \ ------------------------------\
30208 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
30209 \ ------------------------------\
30210 MOV #SLEEP,X \ replace default background process
30211 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
30212 MOV #WARM,X \ replace default WARM
30213 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
30214 MOV X,PC \ then execute it
30217 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
30221 CODE 20_US \ n -- n * 20 us
30222 BEGIN \ here we presume that LCD_TIM_IFG = 1...
30224 BIT #1,&LCD_TIM_CTL \ 3
30225 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
30226 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
30228 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
30233 CODE TOP_LCD \ LCD Sample
30234 \ \ if write : %xxxxWWWW --
30235 \ \ if read : -- %0000RRRR
30236 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30237 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30238 0= IF \ write LCD bits pattern
30239 AND.B #LCD_DB,TOS \
30240 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30241 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30244 THEN \ read LCD bits pattern
30247 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30248 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30249 AND.B #LCD_DB,TOS \
30253 CODE LCD_WRC \ char -- Write Char
30254 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30256 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
30257 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
30258 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30259 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30260 COLON \ high level word starts here
30261 TOP_LCD 2 20_US \ write high nibble first
30265 CODE LCD_WRF \ func -- Write Fonction
30266 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30270 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
30271 : LCD_HOME $02 LCD_WRF 100 20_us ;
30273 \ [UNDEFINED] OR [IF]
30275 \ \ https://forth-standard.org/standard/core/OR
30276 \ \ C OR x1 x2 -- x3 logical OR
30284 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
30285 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
30286 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
30287 \ : LCD_FN_SET $20 OR LCD_WrF ;
30288 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
30289 \ : LCD_GOTO $80 OR LCD_WrF ;
30292 \ CODE LCD_RDS \ -- status Read Status
30293 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30294 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30295 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30296 \ COLON \ starts a FORTH word
30297 \ TOP_LCD 2 20_us \ -- %0000HHHH
30298 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
30299 \ HI2LO \ switch from FORTH to assembler
30300 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
30301 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
30302 \ MOV @RSP+,IP \ restore IP saved by COLON
30306 \ CODE LCD_RDC \ -- char Read Char
30307 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30312 \ ******************************\
30313 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30314 \ ******************************\
30315 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30316 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
30317 BIT.B #SW2,&SW2_IN \ test switch S2
30318 0= IF \ case of switch S2 pressed
30319 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30321 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
30324 BIT.B #SW1,&SW1_IN \ test switch S1 input
30325 0= IF \ case of Switch S1 pressed
30326 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30328 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30332 BW1 \ from quit on truncated RC5 message, repeated RC5 command
30336 \ ******************************\
30337 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30338 \ ******************************\
30339 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30340 \ ******************************\
30341 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30342 \ \ SMclock = 8|16|24 MHz
30343 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30344 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30345 \ \ SR(9)=new Toggle bit memory (ADD on)
30346 \ ******************************\
30347 \ RC5_FirstStartBitHalfCycle: \
30348 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30349 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30350 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
30351 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
30353 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
30354 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
30356 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
30357 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
30359 MOV #1778,X \ RC5_Period * 1us
30360 MOV #14,W \ count of loop
30362 \ ******************************\
30363 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
30364 \ ******************************\ |
30365 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30366 \ RC5_Compute_3/4_Period: \ |
30367 RRUM #1,X \ X=1/2 cycle |
30370 ADD X,Y \ Y=3/4 cycle
30371 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
30373 \ ******************************\
30374 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30375 \ ******************************\
30376 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30377 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
30378 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30379 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30380 SUB #1,W \ decrement count loop
30381 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
30382 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30383 0<> WHILE \ ----> out of loop ----+
30384 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30386 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
30387 CMP Y,X \ 1 | cycle time out of bound ?
30388 U>= IF \ 2 ^ | yes:
30389 BIC #$30,&RC5_TIM_CTL \ | | stop timer
30390 GOTO BW1 \ | | quit on truncated RC5 message
30392 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
30394 REPEAT \ ----> loop back --+ | with X = new RC5_period value
30395 \ ******************************\ |
30396 \ RC5_SampleEndOf: \ <---------------------+
30397 \ ******************************\
30398 BIC #$30,&RC5_TIM_CTL \ stop timer
30399 \ ******************************\
30400 \ RC5_ComputeNewRC5word \
30401 \ ******************************\
30402 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
30403 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
30404 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
30405 \ ******************************\
30406 \ RC5_ComputeC6bit \
30407 \ ******************************\
30408 BIT #BIT14,T \ test /C6 bit in T
30409 0= IF BIS #BIT6,X \ set C6 bit in X
30410 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
30411 \ ******************************\
30412 \ RC5_CommandByteIsDone \ -- BASE RC5_code
30413 \ ******************************\
30414 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30415 \ ******************************\
30416 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
30417 XOR @RSP,T \ (new XOR old) Toggle bits
30418 BIT #UF10,T \ repeated RC5_command ?
30419 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
30420 XOR #UF10,0(RSP) \ 5 toggle bit memory
30421 \ ******************************\
30422 \ Display IR_RC5 code \
30423 \ ******************************\
30424 SUB #8,PSP \ TOS -- x x x x TOS
30425 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
30426 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
30427 MOV #$10,&BASEADR \ set hexadecimal base
30428 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
30429 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
30430 LO2HI \ switch from assembler to FORTH
30431 LCD_CLEAR \ set LCD cursor at home
30432 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
30433 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
30434 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
30435 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
30436 HI2LO \ -- switch from FORTH to assembler
30437 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
30438 MOV @PSP+,TOS \ -- TOS
30442 \ ------------------------------\
30444 \ ------------------------------\
30446 \ ... \ insert here your background task
30449 CALL &RXON \ comment this line to disable TERMINAL
30451 \ ******************************\
30452 \ here start all interrupts \
30453 \ ******************************\
30454 \ here return all interrupts \
30455 \ ******************************\
30459 \ ------------------------------\
30460 CODE STOP \ stops multitasking, must to be used before downloading app
30461 \ ------------------------------\
30462 \ restore default action of primary DEFERred word SLEEP (assembly version)
30463 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
30464 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30465 MOV X,-2(X) \ restore the default background
30466 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30467 ['] WARM >BODY IS WARM \ restore the default WARM
30469 ." RC5toLCD is removed. type START to restart"
30470 COLD \ performs reset to reset all interrupt vectors.
30473 \ ------------------------------\
30474 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
30475 \ ------------------------------\
30476 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30477 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30478 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30479 \ -- \ID input divider \ 10 = /4
30480 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30481 \ - \TBCLR TimerB Clear
30484 \ -------------------------------\
30485 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30486 \ -- \CM Capture Mode
30491 \ --- \OUTMOD \ 011 = set/reset
30497 \ -------------------------------\
30499 \ -------------------------------\
30501 \ ------------------------------\
30502 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30503 \ ------------------------------\
30504 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30505 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30506 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30507 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30509 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30510 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30512 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30513 \ ------------------------------\
30514 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30515 \ ------------------------------\
30516 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30517 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30518 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30519 \ ------------------------------\
30520 BIS.B #LCDVo,&LCDVo_DIR \
30521 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30522 \ ------------------------------\
30523 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30524 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30525 \ ------------------------------\
30526 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30527 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30528 \ ******************************\
30530 \ ******************************\
30531 BIS.B #RC5,&IR_IE \ enable RC5_Int
30532 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30533 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30534 \ ******************************\
30535 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30536 \ ******************************\
30537 \ %01 0001 0100 \ TAxCTL
30538 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30539 \ -- \ ID divided by 1
30540 \ -- \ MC MODE = up to TAxCCRn
30541 \ - \ TACLR clear timer count
30544 \ ------------------------------\
30545 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30546 \ ------------------------------\
30548 \ --- \ TAIDEX pre divisor
30549 \ ------------------------------\
30550 \ %0000 0000 0000 0101 \ TAxCCR0
30551 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30552 \ ------------------------------\
30553 \ %0000 0000 0001 0000 \ TAxCCTL0
30554 \ - \ CAP capture/compare mode = compare
30557 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30558 \ ------------------------------\
30559 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30560 \ ------------------------------\
30561 \ define LPM mode for ACCEPT \
30562 \ ------------------------------\
30563 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30564 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30565 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30566 \ ------------------------------\
30568 \ ------------------------------\
30569 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
30570 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30571 \ ------------------------------\
30572 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30573 \ ------------------------------\
30574 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
30575 \ CMP #2,Y \ Power_ON event
30576 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30578 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
30580 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30582 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30584 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30585 \ ------------------------------\
30587 \ ------------------------------\
30589 \ ------------------------------\
30590 #1000 20_US \ 1- wait 20 ms
30591 %011 TOP_LCD \ 2- send DB5=DB4=1
30592 #205 20_US \ 3- wait 4,1 ms
30593 %011 TOP_LCD \ 4- send again DB5=DB4=1
30594 #5 20_US \ 5- wait 0,1 ms
30595 %011 TOP_LCD \ 6- send again again DB5=DB4=1
30596 #2 20_US \ wait 40 us = LCD cycle
30597 %010 TOP_LCD \ 7- send DB5=1 DB4=0
30598 #2 20_US \ wait 40 us = LCD cycle
30599 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30600 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30601 LCD_CLEAR \ 10- "LCD_Clear"
30602 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30603 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30604 LCD_CLEAR \ 10- "LCD_Clear"
30605 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30606 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30607 CR ." I love you" \ display message on LCD
30608 ['] CR >BODY IS CR \ CR executes its default value
30609 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
30610 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30611 ABORT \ ...and end APP_INIT with ABORT, no return.
30614 \ ------------------------------\
30615 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
30616 \ ------------------------------\
30617 MOV #SLEEP,X \ replace default background process
30618 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
30619 MOV #WARM,X \ replace default WARM
30620 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
30621 MOV X,PC \ then execute it
30624 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
30628 CODE 20_US \ n -- n * 20 us
30629 BEGIN \ here we presume that LCD_TIM_IFG = 1...
30631 BIT #1,&LCD_TIM_CTL \ 3
30632 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
30633 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
30635 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
30640 CODE TOP_LCD \ LCD Sample
30641 \ \ if write : %xxxxWWWW --
30642 \ \ if read : -- %0000RRRR
30643 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30644 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30645 0= IF \ write LCD bits pattern
30646 AND.B #LCD_DB,TOS \
30647 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30648 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30651 THEN \ read LCD bits pattern
30654 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30655 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30656 AND.B #LCD_DB,TOS \
30660 CODE LCD_WRC \ char -- Write Char
30661 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30663 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
30664 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
30665 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30666 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30667 COLON \ high level word starts here
30668 TOP_LCD 2 20_US \ write high nibble first
30672 CODE LCD_WRF \ func -- Write Fonction
30673 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30677 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
30678 : LCD_HOME $02 LCD_WRF 100 20_us ;
30680 \ [UNDEFINED] OR [IF]
30682 \ \ https://forth-standard.org/standard/core/OR
30683 \ \ C OR x1 x2 -- x3 logical OR
30691 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
30692 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
30693 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
30694 \ : LCD_FN_SET $20 OR LCD_WrF ;
30695 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
30696 \ : LCD_GOTO $80 OR LCD_WrF ;
30699 \ CODE LCD_RDS \ -- status Read Status
30700 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30701 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30702 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30703 \ COLON \ starts a FORTH word
30704 \ TOP_LCD 2 20_us \ -- %0000HHHH
30705 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
30706 \ HI2LO \ switch from FORTH to assembler
30707 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
30708 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
30709 \ MOV @RSP+,IP \ restore IP saved by COLON
30713 \ CODE LCD_RDC \ -- char Read Char
30714 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30719 \ ******************************\
30720 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30721 \ ******************************\
30722 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30723 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
30724 BIT.B #SW2,&SW2_IN \ test switch S2
30725 0= IF \ case of switch S2 pressed
30726 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30728 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
30731 BIT.B #SW1,&SW1_IN \ test switch S1 input
30732 0= IF \ case of Switch S1 pressed
30733 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30735 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30739 BW1 \ from quit on truncated RC5 message, repeated RC5 command
30743 \ ******************************\
30744 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30745 \ ******************************\
30746 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30747 \ ******************************\
30748 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30749 \ \ SMclock = 8|16|24 MHz
30750 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30751 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30752 \ \ SR(9)=new Toggle bit memory (ADD on)
30753 \ ******************************\
30754 \ RC5_FirstStartBitHalfCycle: \
30755 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30756 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30757 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
30758 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
30760 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
30761 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
30763 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
30764 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
30766 MOV #1778,X \ RC5_Period * 1us
30767 MOV #14,W \ count of loop
30769 \ ******************************\
30770 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
30771 \ ******************************\ |
30772 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30773 \ RC5_Compute_3/4_Period: \ |
30774 RRUM #1,X \ X=1/2 cycle |
30777 ADD X,Y \ Y=3/4 cycle
30778 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
30780 \ ******************************\
30781 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30782 \ ******************************\
30783 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30784 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
30785 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30786 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30787 SUB #1,W \ decrement count loop
30788 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
30789 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30790 0<> WHILE \ ----> out of loop ----+
30791 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30793 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
30794 CMP Y,X \ 1 | cycle time out of bound ?
30795 U>= IF \ 2 ^ | yes:
30796 BIC #$30,&RC5_TIM_CTL \ | | stop timer
30797 GOTO BW1 \ | | quit on truncated RC5 message
30799 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
30801 REPEAT \ ----> loop back --+ | with X = new RC5_period value
30802 \ ******************************\ |
30803 \ RC5_SampleEndOf: \ <---------------------+
30804 \ ******************************\
30805 BIC #$30,&RC5_TIM_CTL \ stop timer
30806 \ ******************************\
30807 \ RC5_ComputeNewRC5word \
30808 \ ******************************\
30809 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
30810 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
30811 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
30812 \ ******************************\
30813 \ RC5_ComputeC6bit \
30814 \ ******************************\
30815 BIT #BIT14,T \ test /C6 bit in T
30816 0= IF BIS #BIT6,X \ set C6 bit in X
30817 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
30818 \ ******************************\
30819 \ RC5_CommandByteIsDone \ -- BASE RC5_code
30820 \ ******************************\
30821 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30822 \ ******************************\
30823 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
30824 XOR @RSP,T \ (new XOR old) Toggle bits
30825 BIT #UF10,T \ repeated RC5_command ?
30826 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
30827 XOR #UF10,0(RSP) \ 5 toggle bit memory
30828 \ ******************************\
30829 \ Display IR_RC5 code \
30830 \ ******************************\
30831 SUB #8,PSP \ TOS -- x x x x TOS
30832 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
30833 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
30834 MOV #$10,&BASEADR \ set hexadecimal base
30835 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
30836 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
30837 LO2HI \ switch from assembler to FORTH
30838 LCD_CLEAR \ set LCD cursor at home
30839 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
30840 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
30841 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
30842 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
30843 HI2LO \ -- switch from FORTH to assembler
30844 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
30845 MOV @PSP+,TOS \ -- TOS
30849 \ ------------------------------\
30851 \ ------------------------------\
30853 \ ... \ insert here your background task
30856 CALL &RXON \ comment this line to disable TERMINAL
30858 \ ******************************\
30859 \ here start all interrupts \
30860 \ ******************************\
30861 \ here return all interrupts \
30862 \ ******************************\
30866 \ ------------------------------\
30867 CODE STOP \ stops multitasking, must to be used before downloading app
30868 \ ------------------------------\
30869 \ restore default action of primary DEFERred word SLEEP (assembly version)
30870 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
30871 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30872 MOV X,-2(X) \ restore the default background
30873 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30874 ['] WARM >BODY IS WARM \ restore the default WARM
30876 ." RC5toLCD is removed. type START to restart"
30877 COLD \ performs reset to reset all interrupt vectors.
30880 \ ------------------------------\
30881 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
30882 \ ------------------------------\
30883 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30884 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30885 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30886 \ -- \ID input divider \ 10 = /4
30887 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30888 \ - \TBCLR TimerB Clear
30891 \ -------------------------------\
30892 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30893 \ -- \CM Capture Mode
30898 \ --- \OUTMOD \ 011 = set/reset
30904 \ -------------------------------\
30906 \ -------------------------------\
30908 \ ------------------------------\
30909 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30910 \ ------------------------------\
30911 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30912 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30913 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30914 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30916 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30917 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30919 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30920 \ ------------------------------\
30921 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30922 \ ------------------------------\
30923 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30924 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30925 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30926 \ ------------------------------\
30927 BIS.B #LCDVo,&LCDVo_DIR \
30928 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30929 \ ------------------------------\
30930 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30931 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30932 \ ------------------------------\
30933 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30934 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30935 \ ******************************\
30937 \ ******************************\
30938 BIS.B #RC5,&IR_IE \ enable RC5_Int
30939 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30940 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30941 \ ******************************\
30942 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30943 \ ******************************\
30944 \ %01 0001 0100 \ TAxCTL
30945 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30946 \ -- \ ID divided by 1
30947 \ -- \ MC MODE = up to TAxCCRn
30948 \ - \ TACLR clear timer count
30951 \ ------------------------------\
30952 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30953 \ ------------------------------\
30955 \ --- \ TAIDEX pre divisor
30956 \ ------------------------------\
30957 \ %0000 0000 0000 0101 \ TAxCCR0
30958 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30959 \ ------------------------------\
30960 \ %0000 0000 0001 0000 \ TAxCCTL0
30961 \ - \ CAP capture/compare mode = compare
30964 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30965 \ ------------------------------\
30966 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30967 \ ------------------------------\
30968 \ define LPM mode for ACCEPT \
30969 \ ------------------------------\
30970 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30971 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30972 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30973 \ ------------------------------\
30975 \ ------------------------------\
30976 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
30977 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30978 \ ------------------------------\
30979 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30980 \ ------------------------------\
30981 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
30982 \ CMP #2,Y \ Power_ON event
30983 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30985 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
30987 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30989 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30991 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30992 \ ------------------------------\
30994 \ ------------------------------\
30996 \ ------------------------------\
30997 #1000 20_US \ 1- wait 20 ms
30998 %011 TOP_LCD \ 2- send DB5=DB4=1
30999 #205 20_US \ 3- wait 4,1 ms
31000 %011 TOP_LCD \ 4- send again DB5=DB4=1
31001 #5 20_US \ 5- wait 0,1 ms
31002 %011 TOP_LCD \ 6- send again again DB5=DB4=1
31003 #2 20_US \ wait 40 us = LCD cycle
31004 %010 TOP_LCD \ 7- send DB5=1 DB4=0
31005 #2 20_US \ wait 40 us = LCD cycle
31006 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31007 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31008 LCD_CLEAR \ 10- "LCD_Clear"
31009 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31010 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31011 LCD_CLEAR \ 10- "LCD_Clear"
31012 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31013 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31014 CR ." I love you" \ display message on LCD
31015 ['] CR >BODY IS CR \ CR executes its default value
31016 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
31017 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
31018 ABORT \ ...and end APP_INIT with ABORT, no return.
31021 \ ------------------------------\
31022 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
31023 \ ------------------------------\
31024 MOV #SLEEP,X \ replace default background process
31025 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
31026 MOV #WARM,X \ replace default WARM
31027 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
31028 MOV X,PC \ then execute it
31031 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
31035 CODE 20_US \ n -- n * 20 us
31036 BEGIN \ here we presume that LCD_TIM_IFG = 1...
31038 BIT #1,&LCD_TIM_CTL \ 3
31039 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
31040 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
31042 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
31047 CODE TOP_LCD \ LCD Sample
31048 \ \ if write : %xxxxWWWW --
31049 \ \ if read : -- %0000RRRR
31050 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31051 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31052 0= IF \ write LCD bits pattern
31053 AND.B #LCD_DB,TOS \
31054 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31055 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31058 THEN \ read LCD bits pattern
31061 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31062 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31063 AND.B #LCD_DB,TOS \
31067 CODE LCD_WRC \ char -- Write Char
31068 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31070 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31071 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31072 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31073 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31074 COLON \ high level word starts here
31075 TOP_LCD 2 20_US \ write high nibble first
31079 CODE LCD_WRF \ func -- Write Fonction
31080 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31084 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
31085 : LCD_HOME $02 LCD_WRF 100 20_us ;
31087 \ [UNDEFINED] OR [IF]
31089 \ \ https://forth-standard.org/standard/core/OR
31090 \ \ C OR x1 x2 -- x3 logical OR
31098 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
31099 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
31100 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
31101 \ : LCD_FN_SET $20 OR LCD_WrF ;
31102 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
31103 \ : LCD_GOTO $80 OR LCD_WrF ;
31106 \ CODE LCD_RDS \ -- status Read Status
31107 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31108 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31109 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31110 \ COLON \ starts a FORTH word
31111 \ TOP_LCD 2 20_us \ -- %0000HHHH
31112 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31113 \ HI2LO \ switch from FORTH to assembler
31114 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31115 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31116 \ MOV @RSP+,IP \ restore IP saved by COLON
31120 \ CODE LCD_RDC \ -- char Read Char
31121 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31126 \ ******************************\
31127 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31128 \ ******************************\
31129 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
31130 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
31131 BIT.B #SW2,&SW2_IN \ test switch S2
31132 0= IF \ case of switch S2 pressed
31133 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
31135 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
31138 BIT.B #SW1,&SW1_IN \ test switch S1 input
31139 0= IF \ case of Switch S1 pressed
31140 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
31142 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
31146 BW1 \ from quit on truncated RC5 message, repeated RC5 command
31150 \ ******************************\
31151 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31152 \ ******************************\
31153 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31154 \ ******************************\
31155 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31156 \ \ SMclock = 8|16|24 MHz
31157 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
31158 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
31159 \ \ SR(9)=new Toggle bit memory (ADD on)
31160 \ ******************************\
31161 \ RC5_FirstStartBitHalfCycle: \
31162 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
31163 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
31164 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
31165 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
31167 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
31168 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
31170 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
31171 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
31173 MOV #1778,X \ RC5_Period * 1us
31174 MOV #14,W \ count of loop
31176 \ ******************************\
31177 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
31178 \ ******************************\ |
31179 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31180 \ RC5_Compute_3/4_Period: \ |
31181 RRUM #1,X \ X=1/2 cycle |
31184 ADD X,Y \ Y=3/4 cycle
31185 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
31187 \ ******************************\
31188 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31189 \ ******************************\
31190 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31191 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
31192 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31193 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31194 SUB #1,W \ decrement count loop
31195 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
31196 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31197 0<> WHILE \ ----> out of loop ----+
31198 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31200 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
31201 CMP Y,X \ 1 | cycle time out of bound ?
31202 U>= IF \ 2 ^ | yes:
31203 BIC #$30,&RC5_TIM_CTL \ | | stop timer
31204 GOTO BW1 \ | | quit on truncated RC5 message
31206 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
31208 REPEAT \ ----> loop back --+ | with X = new RC5_period value
31209 \ ******************************\ |
31210 \ RC5_SampleEndOf: \ <---------------------+
31211 \ ******************************\
31212 BIC #$30,&RC5_TIM_CTL \ stop timer
31213 \ ******************************\
31214 \ RC5_ComputeNewRC5word \
31215 \ ******************************\
31216 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
31217 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
31218 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
31219 \ ******************************\
31220 \ RC5_ComputeC6bit \
31221 \ ******************************\
31222 BIT #BIT14,T \ test /C6 bit in T
31223 0= IF BIS #BIT6,X \ set C6 bit in X
31224 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
31225 \ ******************************\
31226 \ RC5_CommandByteIsDone \ -- BASE RC5_code
31227 \ ******************************\
31228 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31229 \ ******************************\
31230 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
31231 XOR @RSP,T \ (new XOR old) Toggle bits
31232 BIT #UF10,T \ repeated RC5_command ?
31233 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
31234 XOR #UF10,0(RSP) \ 5 toggle bit memory
31235 \ ******************************\
31236 \ Display IR_RC5 code \
31237 \ ******************************\
31238 SUB #8,PSP \ TOS -- x x x x TOS
31239 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
31240 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
31241 MOV #$10,&BASEADR \ set hexadecimal base
31242 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
31243 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
31244 LO2HI \ switch from assembler to FORTH
31245 LCD_CLEAR \ set LCD cursor at home
31246 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
31247 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
31248 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
31249 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
31250 HI2LO \ -- switch from FORTH to assembler
31251 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
31252 MOV @PSP+,TOS \ -- TOS
31256 \ ------------------------------\
31258 \ ------------------------------\
31260 \ ... \ insert here your background task
31263 CALL &RXON \ comment this line to disable TERMINAL
31265 \ ******************************\
31266 \ here start all interrupts \
31267 \ ******************************\
31268 \ here return all interrupts \
31269 \ ******************************\
31273 \ ------------------------------\
31274 CODE STOP \ stops multitasking, must to be used before downloading app
31275 \ ------------------------------\
31276 \ restore default action of primary DEFERred word SLEEP (assembly version)
31277 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
31278 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
31279 MOV X,-2(X) \ restore the default background
31280 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
31281 ['] WARM >BODY IS WARM \ restore the default WARM
31283 ." RC5toLCD is removed. type START to restart"
31284 COLD \ performs reset to reset all interrupt vectors.
31287 \ ------------------------------\
31288 CODE APP_INIT \ this routine completes the init of system, i.e. FORTH + this app.
31289 \ ------------------------------\
31290 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
31291 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31292 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31293 \ -- \ID input divider \ 10 = /4
31294 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
31295 \ - \TBCLR TimerB Clear
31298 \ -------------------------------\
31299 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31300 \ -- \CM Capture Mode
31305 \ --- \OUTMOD \ 011 = set/reset
31311 \ -------------------------------\
31313 \ -------------------------------\
31315 \ ------------------------------\
31316 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
31317 \ ------------------------------\
31318 MOV #%1011010100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
31319 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
31320 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
31321 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
31323 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
31324 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
31326 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
31327 \ ------------------------------\
31328 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
31329 \ ------------------------------\
31330 MOV #%01100000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
31331 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
31332 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31333 \ ------------------------------\
31334 BIS.B #LCDVo,&LCDVo_DIR \
31335 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
31336 \ ------------------------------\
31337 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31338 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31339 \ ------------------------------\
31340 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31341 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31342 \ ******************************\
31344 \ ******************************\
31345 BIS.B #RC5,&IR_IE \ enable RC5_Int
31346 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31347 MOV #RC5_INT,&IR_Vec \ init interrupt vector
31348 \ ******************************\
31349 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
31350 \ ******************************\
31351 \ %01 0001 0100 \ TAxCTL
31352 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
31353 \ -- \ ID divided by 1
31354 \ -- \ MC MODE = up to TAxCCRn
31355 \ - \ TACLR clear timer count
31358 \ ------------------------------\
31359 MOV #%0100010100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
31360 \ ------------------------------\
31362 \ --- \ TAIDEX pre divisor
31363 \ ------------------------------\
31364 \ %0000 0000 0000 0101 \ TAxCCR0
31365 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
31366 \ ------------------------------\
31367 \ %0000 0000 0001 0000 \ TAxCCTL0
31368 \ - \ CAP capture/compare mode = compare
31371 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
31372 \ ------------------------------\
31373 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
31374 \ ------------------------------\
31375 \ define LPM mode for ACCEPT \
31376 \ ------------------------------\
31377 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31378 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31379 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31380 \ ------------------------------\
31382 \ ------------------------------\
31383 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
31384 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
31385 \ ------------------------------\
31386 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
31387 \ ------------------------------\
31388 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
31389 \ CMP #2,Y \ Power_ON event
31390 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
31392 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
31394 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
31396 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
31398 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
31399 \ ------------------------------\
31401 \ ------------------------------\
31403 \ ------------------------------\
31404 #1000 20_US \ 1- wait 20 ms
31405 %011 TOP_LCD \ 2- send DB5=DB4=1
31406 #205 20_US \ 3- wait 4,1 ms
31407 %011 TOP_LCD \ 4- send again DB5=DB4=1
31408 #5 20_US \ 5- wait 0,1 ms
31409 %011 TOP_LCD \ 6- send again again DB5=DB4=1
31410 #2 20_US \ wait 40 us = LCD cycle
31411 %010 TOP_LCD \ 7- send DB5=1 DB4=0
31412 #2 20_US \ wait 40 us = LCD cycle
31413 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31414 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31415 LCD_CLEAR \ 10- "LCD_Clear"
31416 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31417 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31418 LCD_CLEAR \ 10- "LCD_Clear"
31419 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31420 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31421 CR ." I love you" \ display message on LCD
31422 ['] CR >BODY IS CR \ CR executes its default value
31423 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
31424 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
31425 ABORT \ ...and end APP_INIT with ABORT, no return.
31428 \ ------------------------------\
31429 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
31430 \ ------------------------------\
31431 MOV #SLEEP,X \ replace default background process
31432 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
31433 MOV #WARM,X \ replace default WARM
31434 MOV #APP_INIT,2(X) \ by RC5toLCD APP_INIT
31435 MOV X,PC \ then execute it
31441 ; downloading RC5toLCD.4th is done
31442 RST_HERE ; this app is protected against <reset>