1 ; -----------------------------------
2 ; prog100k.4th, to test speed of downloading
3 ; -----------------------------------
6 NOECHO ; if an error occurs during download, comment this line then download again
8 \ Copyright (C) <2016> <J.M. THOORENS>
10 \ This program is free software: you can redistribute it and/or modify
11 \ it under the terms of the GNU General Public License as published by
12 \ the Free Software Foundation, either version 3 of the License, or
13 \ (at your option) any later version.
15 \ This program is distributed in the hope that it will be useful,
16 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
17 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 \ GNU General Public License for more details.
20 \ You should have received a copy of the GNU General Public License
21 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
24 \ ===========================================================================
25 \ remember: for good downloading to target, all lines must be ended with CR+LF !
26 \ ===========================================================================
30 \ R4 to R7 must be saved before use and restored after
31 \ scratch registers Y to S are free for use
32 \ under interrupt, IP is free for use
34 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, R7, R6, R5, R4
35 \ example : PUSHM IP,Y
37 \ POPM order : R4, R5, R6, R7, Y, X, W, T, S, IP,TOS,PSP
40 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
41 \ ASSEMBLER conditionnal usage before ?JMP ?GOTO : S< S>= U< U>= 0= 0<> 0<
43 \ FORTH conditionnal : 0= 0< = < > U<
45 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
46 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
47 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
49 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
50 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
51 \ without usage of an auxiliary 5V to feed the LCD_Vo
52 \ and without potentiometer to adjust the LCD contrast :
53 \ to adjust LCD contrast, just press S1 (-) or S2 (+)
54 \ LCDVo current consumption ~ 500 uA.
56 \ ===================================================================================
57 \ notice : adjust TA0EX0,TB0CTL,TB0EX0 and 20_us to the target frequency if <> 8MHz !
58 \ ===================================================================================
61 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
63 \ GND <-------+---0V0----------> 1 LCD_Vss
64 \ VCC >------ | --3V6-----+----> 2 LCD_Vdd
71 \ TB0.2 >---||--+--^/\/\/v--+----> 3 LCD_Vo (= 0V6 without modulation)
72 \ -------------------------> 4 LCD_RW
73 \ -------------------------> 5 LCD_RW
74 \ -------------------------> 6 LCD_EN
75 \ <------------------------> 11 LCD_DB4
76 \ <------------------------> 12 LCD_DB5
77 \ <------------------------> 13 LCD_DB5
78 \ <------------------------> 14 LCD_DB7
80 \ <----- LCD contrast + <--- Sw1 <--- (finger) :-)
81 \ <----- LCD contrast - <--- Sw2 <--- (finger) :-)
83 \ rc5 <--- OUT IR_Receiver (1 TSOP32236)
86 CODE MAX \ n1 n2 -- n3 signed maximum
94 CODE MIN \ n1 n2 -- n3 signed minimum
102 : U.R \ u n -- display u unsigned in n width (n >= 2)
104 R> OVER - 0 MAX SPACES TYPE
108 CODE 20_US \ n -- n * 20 us
109 BEGIN \ 3 cycles loop + 6~
110 \ MOV #5,W \ 3 MCLK = 1 MHz
111 \ MOV #23,W \ 3 MCLK = 4 MHz
112 MOV #51,W \ 3 MCLK = 8 MHz
113 \ MOV #104,W \ 3 MCLK = 16 MHz
114 \ MOV #158,W \ 3 MCLK = 24 MHz
115 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
125 CODE TOP_LCD \ LCD Sample
126 \ \ if write : %xxxxWWWW --
127 \ \ if read : -- %0000RRRR
128 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
129 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
130 0= IF \ write LCD bits pattern
132 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
133 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
136 THEN \ read LCD bits pattern
139 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
140 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
146 CODE LCD_W \ byte -- write byte to LCD
148 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
149 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
150 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
151 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
152 COLON \ high level word starts here
153 TOP_LCD 2 20_US \ write high nibble first
158 CODE LCD_WrC \ char -- Write Char
159 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
164 CODE LCD_WrF \ func -- Write Fonction
165 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
171 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
176 $02 LCD_WrF 100 20_us
180 \ : LCD_Entry_set $04 OR LCD_WrF ;
182 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
184 \ : LCD_Display_Shift $10 OR LCD_WrF ;
186 \ : LCD_Fn_Set $20 OR LCD_WrF ;
188 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
190 \ : LCD_Goto $80 OR LCD_WrF ;
192 \ CODE LCD_R \ -- byte read byte from LCD
193 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
194 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
195 \ COLON \ starts a FORTH word
196 \ TOP_LCD 2 20_us \ -- %0000HHHH
197 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
198 \ HI2LO \ switch from FORTH to assembler
199 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
200 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
201 \ MOV @RSP+,IP \ restore IP saved by COLON
206 \ CODE LCD_RdS \ -- status Read Status
207 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
212 \ CODE LCD_RdC \ -- char Read Char
213 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
218 \ -------------+------+------+------+------++---+---+---+---+---------+
219 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
220 \ -------------+------+------+------+------++---+---+---+---+---------+
221 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
222 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
223 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
224 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
225 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
226 \ -------------+------+------+------+------++---+---+---+---+---------+
229 \ ******************************\
230 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
231 \ ******************************\
232 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
233 \ ------------------------------\
234 \ define LPM mode for ACCEPT \
235 \ ------------------------------\
236 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
237 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
238 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
239 BIT.B #SW2,&SW2_IN \ test switch S2
240 0= IF \ case of switch S2 pressed
241 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
243 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
246 BIT.B #SW1,&SW1_IN \ test switch S1 input
247 0= IF \ case of Switch S1 pressed
248 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
250 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
254 RETI \ CPU is ON, GIE is OFF
259 \ ------------------------------\
260 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
261 \ ******************************\
262 ASM RC5_INT \ wake up on Px.RC5 change interrupt
263 \ ******************************\
264 \ \ in : SR(9)=old Toggle bit memory (ADD on)
265 \ \ SMclock = 8|16|24 MHz
266 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
267 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
268 \ \ SR(9)=new Toggle bit memory (ADD on)
269 \ ------------------------------\
270 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
271 \ ------------------------------\
272 \ define LPM mode for ACCEPT \
273 \ ------------------------------\
274 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
275 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
276 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
277 \ ------------------------------\
278 \ RC5_FirstStartBitHalfCycle: \
279 \ ------------------------------\
280 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
281 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
282 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
283 MOV #1778,X \ RC5_Period in us
284 MOV #14,W \ count of loop
286 \ ------------------------------\
287 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
288 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
289 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
290 \ RC5_Compute_3/4_Period: \ |
291 RRUM #1,X \ X=1/2 cycle |
295 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
296 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
298 \ ------------------------------\
299 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
300 \ ------------------------------\
301 BIT.B #RC5,&IR_IN \ C_flag = IR bit
302 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
303 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
304 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
305 SUB #1,W \ decrement count loop
306 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
307 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
308 0<> WHILE \ ----> out of loop ----+
309 \ RC5_compute_7/4_Time_out: \ |
310 ADD X,Y \ | out of bound = 7/4 period
311 \ RC5_WaitHalfCycleP1.2_IFG: \ |
313 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
314 0>= IF \ | if cycle time out of bound
315 BIC #$30,&TA0CTL \ | stop timer_A0
316 RETI \ | then quit to do nothing
318 \ ------------------------------\ |
319 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
321 MOV &TA0R,X \ | | get new RC5_period value
322 REPEAT \ ----> loop back --+ |
323 \ ------------------------------\ |
324 \ RC5_SampleEndOf: \ <---------------------+
325 \ ------------------------------\
326 BIC #$30,&TA0CTL \ stop timer_A0
327 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
328 \ ******************************\
329 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
330 \ ******************************\
331 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
332 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
333 XOR IP,X \ (new XOR old) Toggle bit (13)
334 BIT #BIT13,X \ X(13) = New_RC5_command
335 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
337 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
338 \ ******************************\
339 \ RC5_ComputeNewRC5word \
340 \ ******************************\
342 MOV &BASE,2(PSP) \ save variable BASE before use
343 MOV TOS,0(PSP) \ save TOS before use
344 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
345 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
346 \ ******************************\
348 \ ******************************\
349 BIT #$4000,IP \ test /C6 bit in IP
350 0= IF BIS #$40,TOS \ set C6 bit in S
351 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
352 \ ******************************\
353 \ RC5_CommandByteIsDone \ RC5_code --
354 \ ******************************\
356 \ ------------------------------\
357 \ Display IR_RC5 code \
358 \ ------------------------------\
359 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
360 \ ------------------------------\
361 LO2HI \ switch from assembler to FORTH
362 ['] LCD_CLEAR IS CR \ redirects CR
363 ['] LCD_WrC IS EMIT \ redirects EMIT
364 $10 BASE ! \ change BASE to hexadecimal
365 CR ." $" 2 U.R \ print IR_RC5 code
366 ['] (CR) IS CR \ restore CR
367 ['] (EMIT) IS EMIT \ restore EMIT
368 HI2LO \ switch from FORTH to assembler
369 \ ------------------------------\
370 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
371 \ ------------------------------\
372 MOV @PSP+,&BASE \ restore variable BASE
373 RETI \ CPU is ON, GIE is OFF
378 \ ------------------------------\
379 \ TB0CTL = %0000 0010 1001 0100\$3C0
380 \ - - \CNTL Counter lentgh \ 00 = 16 bits
381 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
382 \ -- \ID input divider \ 10 = /4
383 \ -- \MC Mode Control \ 01 = up to TB0CCR0
384 \ - \TBCLR TimerB Clear
387 \ --------------------------------\\
388 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
389 \ -- \CM Capture Mode
394 \ --- \OUTMOD \ 011 = set/reset
400 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
402 \ ------------------------------\
403 \ set TimerB to make 50kHz PWM \
404 \ ------------------------------\
405 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
406 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
407 \ ------------------------------\
408 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
409 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
410 \ ------------------------------\
411 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
412 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
413 \ ------------------------------\
414 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
415 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
416 \ ------------------------------\
417 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
418 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
419 \ ------------------------------\
420 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
421 \ ------------------------------\
422 \ set TimerB to generate PWM for LCD_Vo
423 \ ------------------------------\
424 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
425 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
426 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
427 \ ------------------------------\
428 BIS.B #LCDVo,&LCDVo_DIR \
429 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
430 \ ------------------------------\
431 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
432 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
433 \ ------------------------------\
434 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
435 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
436 \ ------------------------------\
437 \ WDT interval init part \
438 \ ------------------------------\
439 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
440 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
441 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
442 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
443 \ ------------------------------\
445 \ ------------------------------\
446 BIS.B #RC5,&IR_IE \ enable RC5_Int
447 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
448 \ ------------------------------\
449 \ init interrupt vectors
450 \ ------------------------------\
451 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
452 MOV #RC5_INT,&IR_Vec \ init interrupt vector
453 \ ------------------------------\
454 \ define LPM mode for ACCEPT \
455 \ ------------------------------\
456 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
457 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
458 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
460 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
462 \ ------------------------------\
464 \ ------------------------------\
465 $03E8 20_US \ 1- wait 20 ms
466 $03 TOP_LCD \ 2- send DB5=DB4=1
467 $CD 20_US \ 3- wait 4,1 ms
468 $03 TOP_LCD \ 4- send again DB5=DB4=1
469 $5 20_US \ 5- wait 0,1 ms
470 $03 TOP_LCD \ 6- send again again DB5=DB4=1
471 $2 20_US \ wait 40 us = LCD cycle
472 $02 TOP_LCD \ 7- send DB5=1 DB4=0
473 $2 20_US \ wait 40 us = LCD cycle
474 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
475 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
476 LCD_Clear \ 10- "LCD_Clear"
477 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
478 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
479 LCD_Clear \ 10- "LCD_Clear"
480 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
481 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
483 ['] (CR) IS CR \ ' (CR) is CR
484 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
486 ." RC5toLCD is running. Type STOP to quit"
487 \ NOECHO \ uncomment to run this app without terminal connexion
488 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
489 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
493 : STOP \ stops multitasking, must to be used before downloading app
494 ['] (WARM) IS WARM \ remove START app from FORTH init process
495 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
503 CODE MAX \ n1 n2 -- n3 signed maximum
511 CODE MIN \ n1 n2 -- n3 signed minimum
519 : U.R \ u n -- display u unsigned in n width (n >= 2)
521 R> OVER - 0 MAX SPACES TYPE
525 CODE 20_US \ n -- n * 20 us
526 BEGIN \ 3 cycles loop + 6~
527 \ MOV #5,W \ 3 MCLK = 1 MHz
528 \ MOV #23,W \ 3 MCLK = 4 MHz
529 MOV #51,W \ 3 MCLK = 8 MHz
530 \ MOV #104,W \ 3 MCLK = 16 MHz
531 \ MOV #158,W \ 3 MCLK = 24 MHz
532 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
542 CODE TOP_LCD \ LCD Sample
543 \ \ if write : %xxxxWWWW --
544 \ \ if read : -- %0000RRRR
545 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
546 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
547 0= IF \ write LCD bits pattern
549 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
550 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
553 THEN \ read LCD bits pattern
556 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
557 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
563 CODE LCD_W \ byte -- write byte to LCD
565 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
566 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
567 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
568 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
569 COLON \ high level word starts here
570 TOP_LCD 2 20_US \ write high nibble first
575 CODE LCD_WrC \ char -- Write Char
576 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
581 CODE LCD_WrF \ func -- Write Fonction
582 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
588 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
593 $02 LCD_WrF 100 20_us
597 \ : LCD_Entry_set $04 OR LCD_WrF ;
599 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
601 \ : LCD_Display_Shift $10 OR LCD_WrF ;
603 \ : LCD_Fn_Set $20 OR LCD_WrF ;
605 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
607 \ : LCD_Goto $80 OR LCD_WrF ;
609 \ CODE LCD_R \ -- byte read byte from LCD
610 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
611 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
612 \ COLON \ starts a FORTH word
613 \ TOP_LCD 2 20_us \ -- %0000HHHH
614 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
615 \ HI2LO \ switch from FORTH to assembler
616 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
617 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
618 \ MOV @RSP+,IP \ restore IP saved by COLON
623 \ CODE LCD_RdS \ -- status Read Status
624 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
629 \ CODE LCD_RdC \ -- char Read Char
630 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
635 \ -------------+------+------+------+------++---+---+---+---+---------+
636 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
637 \ -------------+------+------+------+------++---+---+---+---+---------+
638 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
639 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
640 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
641 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
642 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
643 \ -------------+------+------+------+------++---+---+---+---+---------+
646 \ ******************************\
647 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
648 \ ******************************\
649 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
650 \ ------------------------------\
651 \ define LPM mode for ACCEPT \
652 \ ------------------------------\
653 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
654 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
655 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
656 BIT.B #SW2,&SW2_IN \ test switch S2
657 0= IF \ case of switch S2 pressed
658 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
660 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
663 BIT.B #SW1,&SW1_IN \ test switch S1 input
664 0= IF \ case of Switch S1 pressed
665 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
667 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
671 RETI \ CPU is ON, GIE is OFF
676 \ ------------------------------\
677 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
678 \ ******************************\
679 ASM RC5_INT \ wake up on Px.RC5 change interrupt
680 \ ******************************\
681 \ \ in : SR(9)=old Toggle bit memory (ADD on)
682 \ \ SMclock = 8|16|24 MHz
683 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
684 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
685 \ \ SR(9)=new Toggle bit memory (ADD on)
686 \ ------------------------------\
687 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
688 \ ------------------------------\
689 \ define LPM mode for ACCEPT \
690 \ ------------------------------\
691 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
692 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
693 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
694 \ ------------------------------\
695 \ RC5_FirstStartBitHalfCycle: \
696 \ ------------------------------\
697 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
698 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
699 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
700 MOV #1778,X \ RC5_Period in us
701 MOV #14,W \ count of loop
703 \ ------------------------------\
704 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
705 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
706 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
707 \ RC5_Compute_3/4_Period: \ |
708 RRUM #1,X \ X=1/2 cycle |
712 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
713 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
715 \ ------------------------------\
716 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
717 \ ------------------------------\
718 BIT.B #RC5,&IR_IN \ C_flag = IR bit
719 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
720 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
721 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
722 SUB #1,W \ decrement count loop
723 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
724 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
725 0<> WHILE \ ----> out of loop ----+
726 \ RC5_compute_7/4_Time_out: \ |
727 ADD X,Y \ | out of bound = 7/4 period
728 \ RC5_WaitHalfCycleP1.2_IFG: \ |
730 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
731 0>= IF \ | if cycle time out of bound
732 BIC #$30,&TA0CTL \ | stop timer_A0
733 RETI \ | then quit to do nothing
735 \ ------------------------------\ |
736 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
738 MOV &TA0R,X \ | | get new RC5_period value
739 REPEAT \ ----> loop back --+ |
740 \ ------------------------------\ |
741 \ RC5_SampleEndOf: \ <---------------------+
742 \ ------------------------------\
743 BIC #$30,&TA0CTL \ stop timer_A0
744 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
745 \ ******************************\
746 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
747 \ ******************************\
748 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
749 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
750 XOR IP,X \ (new XOR old) Toggle bit (13)
751 BIT #BIT13,X \ X(13) = New_RC5_command
752 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
754 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
755 \ ******************************\
756 \ RC5_ComputeNewRC5word \
757 \ ******************************\
759 MOV &BASE,2(PSP) \ save variable BASE before use
760 MOV TOS,0(PSP) \ save TOS before use
761 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
762 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
763 \ ******************************\
765 \ ******************************\
766 BIT #$4000,IP \ test /C6 bit in IP
767 0= IF BIS #$40,TOS \ set C6 bit in S
768 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
769 \ ******************************\
770 \ RC5_CommandByteIsDone \ RC5_code --
771 \ ******************************\
773 \ ------------------------------\
774 \ Display IR_RC5 code \
775 \ ------------------------------\
776 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
777 \ ------------------------------\
778 LO2HI \ switch from assembler to FORTH
779 ['] LCD_CLEAR IS CR \ redirects CR
780 ['] LCD_WrC IS EMIT \ redirects EMIT
781 $10 BASE ! \ change BASE to hexadecimal
782 CR ." $" 2 U.R \ print IR_RC5 code
783 ['] (CR) IS CR \ restore CR
784 ['] (EMIT) IS EMIT \ restore EMIT
785 HI2LO \ switch from FORTH to assembler
786 \ ------------------------------\
787 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
788 \ ------------------------------\
789 MOV @PSP+,&BASE \ restore variable BASE
790 RETI \ CPU is ON, GIE is OFF
795 \ ------------------------------\
796 \ TB0CTL = %0000 0010 1001 0100\$3C0
797 \ - - \CNTL Counter lentgh \ 00 = 16 bits
798 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
799 \ -- \ID input divider \ 10 = /4
800 \ -- \MC Mode Control \ 01 = up to TB0CCR0
801 \ - \TBCLR TimerB Clear
804 \ --------------------------------\\
805 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
806 \ -- \CM Capture Mode
811 \ --- \OUTMOD \ 011 = set/reset
817 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
819 \ ------------------------------\
820 \ set TimerB to make 50kHz PWM \
821 \ ------------------------------\
822 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
823 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
824 \ ------------------------------\
825 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
826 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
827 \ ------------------------------\
828 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
829 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
830 \ ------------------------------\
831 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
832 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
833 \ ------------------------------\
834 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
835 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
836 \ ------------------------------\
837 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
838 \ ------------------------------\
839 \ set TimerB to generate PWM for LCD_Vo
840 \ ------------------------------\
841 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
842 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
843 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
844 \ ------------------------------\
845 BIS.B #LCDVo,&LCDVo_DIR \
846 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
847 \ ------------------------------\
848 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
849 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
850 \ ------------------------------\
851 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
852 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
853 \ ------------------------------\
854 \ WDT interval init part \
855 \ ------------------------------\
856 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
857 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
858 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
859 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
860 \ ------------------------------\
862 \ ------------------------------\
863 BIS.B #RC5,&IR_IE \ enable RC5_Int
864 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
865 \ ------------------------------\
866 \ init interrupt vectors
867 \ ------------------------------\
868 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
869 MOV #RC5_INT,&IR_Vec \ init interrupt vector
870 \ ------------------------------\
871 \ define LPM mode for ACCEPT \
872 \ ------------------------------\
873 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
874 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
875 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
877 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
879 \ ------------------------------\
881 \ ------------------------------\
882 $03E8 20_US \ 1- wait 20 ms
883 $03 TOP_LCD \ 2- send DB5=DB4=1
884 $CD 20_US \ 3- wait 4,1 ms
885 $03 TOP_LCD \ 4- send again DB5=DB4=1
886 $5 20_US \ 5- wait 0,1 ms
887 $03 TOP_LCD \ 6- send again again DB5=DB4=1
888 $2 20_US \ wait 40 us = LCD cycle
889 $02 TOP_LCD \ 7- send DB5=1 DB4=0
890 $2 20_US \ wait 40 us = LCD cycle
891 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
892 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
893 LCD_Clear \ 10- "LCD_Clear"
894 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
895 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
896 LCD_Clear \ 10- "LCD_Clear"
897 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
898 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
900 ['] (CR) IS CR \ ' (CR) is CR
901 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
903 ." RC5toLCD is running. Type STOP to quit"
904 \ NOECHO \ uncomment to run this app without terminal connexion
905 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
906 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
910 : STOP \ stops multitasking, must to be used before downloading app
911 ['] (WARM) IS WARM \ remove START app from FORTH init process
912 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
920 CODE MAX \ n1 n2 -- n3 signed maximum
928 CODE MIN \ n1 n2 -- n3 signed minimum
936 : U.R \ u n -- display u unsigned in n width (n >= 2)
938 R> OVER - 0 MAX SPACES TYPE
942 CODE 20_US \ n -- n * 20 us
943 BEGIN \ 3 cycles loop + 6~
944 \ MOV #5,W \ 3 MCLK = 1 MHz
945 \ MOV #23,W \ 3 MCLK = 4 MHz
946 MOV #51,W \ 3 MCLK = 8 MHz
947 \ MOV #104,W \ 3 MCLK = 16 MHz
948 \ MOV #158,W \ 3 MCLK = 24 MHz
949 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
959 CODE TOP_LCD \ LCD Sample
960 \ \ if write : %xxxxWWWW --
961 \ \ if read : -- %0000RRRR
962 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
963 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
964 0= IF \ write LCD bits pattern
966 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
967 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
970 THEN \ read LCD bits pattern
973 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
974 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
980 CODE LCD_W \ byte -- write byte to LCD
982 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
983 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
984 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
985 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
986 COLON \ high level word starts here
987 TOP_LCD 2 20_US \ write high nibble first
992 CODE LCD_WrC \ char -- Write Char
993 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
998 CODE LCD_WrF \ func -- Write Fonction
999 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1005 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1010 $02 LCD_WrF 100 20_us
1014 \ : LCD_Entry_set $04 OR LCD_WrF ;
1016 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1018 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1020 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1022 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1024 \ : LCD_Goto $80 OR LCD_WrF ;
1026 \ CODE LCD_R \ -- byte read byte from LCD
1027 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1028 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1029 \ COLON \ starts a FORTH word
1030 \ TOP_LCD 2 20_us \ -- %0000HHHH
1031 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1032 \ HI2LO \ switch from FORTH to assembler
1033 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1034 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1035 \ MOV @RSP+,IP \ restore IP saved by COLON
1040 \ CODE LCD_RdS \ -- status Read Status
1041 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1046 \ CODE LCD_RdC \ -- char Read Char
1047 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1052 \ -------------+------+------+------+------++---+---+---+---+---------+
1053 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1054 \ -------------+------+------+------+------++---+---+---+---+---------+
1055 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1056 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1057 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1058 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1059 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1060 \ -------------+------+------+------+------++---+---+---+---+---------+
1063 \ ******************************\
1064 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1065 \ ******************************\
1066 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1067 \ ------------------------------\
1068 \ define LPM mode for ACCEPT \
1069 \ ------------------------------\
1070 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1071 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1072 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1073 BIT.B #SW2,&SW2_IN \ test switch S2
1074 0= IF \ case of switch S2 pressed
1075 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1077 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1080 BIT.B #SW1,&SW1_IN \ test switch S1 input
1081 0= IF \ case of Switch S1 pressed
1082 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1084 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1088 RETI \ CPU is ON, GIE is OFF
1093 \ ------------------------------\
1094 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1095 \ ******************************\
1096 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1097 \ ******************************\
1098 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1099 \ \ SMclock = 8|16|24 MHz
1100 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1101 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1102 \ \ SR(9)=new Toggle bit memory (ADD on)
1103 \ ------------------------------\
1104 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1105 \ ------------------------------\
1106 \ define LPM mode for ACCEPT \
1107 \ ------------------------------\
1108 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1109 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1110 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1111 \ ------------------------------\
1112 \ RC5_FirstStartBitHalfCycle: \
1113 \ ------------------------------\
1114 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1115 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1116 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1117 MOV #1778,X \ RC5_Period in us
1118 MOV #14,W \ count of loop
1120 \ ------------------------------\
1121 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1122 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1123 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1124 \ RC5_Compute_3/4_Period: \ |
1125 RRUM #1,X \ X=1/2 cycle |
1129 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1130 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1132 \ ------------------------------\
1133 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1134 \ ------------------------------\
1135 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1136 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1137 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1138 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1139 SUB #1,W \ decrement count loop
1140 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1141 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1142 0<> WHILE \ ----> out of loop ----+
1143 \ RC5_compute_7/4_Time_out: \ |
1144 ADD X,Y \ | out of bound = 7/4 period
1145 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1147 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1148 0>= IF \ | if cycle time out of bound
1149 BIC #$30,&TA0CTL \ | stop timer_A0
1150 RETI \ | then quit to do nothing
1152 \ ------------------------------\ |
1153 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1155 MOV &TA0R,X \ | | get new RC5_period value
1156 REPEAT \ ----> loop back --+ |
1157 \ ------------------------------\ |
1158 \ RC5_SampleEndOf: \ <---------------------+
1159 \ ------------------------------\
1160 BIC #$30,&TA0CTL \ stop timer_A0
1161 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1162 \ ******************************\
1163 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1164 \ ******************************\
1165 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
1166 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
1167 XOR IP,X \ (new XOR old) Toggle bit (13)
1168 BIT #BIT13,X \ X(13) = New_RC5_command
1169 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
1171 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
1172 \ ******************************\
1173 \ RC5_ComputeNewRC5word \
1174 \ ******************************\
1176 MOV &BASE,2(PSP) \ save variable BASE before use
1177 MOV TOS,0(PSP) \ save TOS before use
1178 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
1179 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
1180 \ ******************************\
1181 \ RC5_ComputeC6bit \
1182 \ ******************************\
1183 BIT #$4000,IP \ test /C6 bit in IP
1184 0= IF BIS #$40,TOS \ set C6 bit in S
1185 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
1186 \ ******************************\
1187 \ RC5_CommandByteIsDone \ RC5_code --
1188 \ ******************************\
1190 \ ------------------------------\
1191 \ Display IR_RC5 code \
1192 \ ------------------------------\
1193 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
1194 \ ------------------------------\
1195 LO2HI \ switch from assembler to FORTH
1196 ['] LCD_CLEAR IS CR \ redirects CR
1197 ['] LCD_WrC IS EMIT \ redirects EMIT
1198 $10 BASE ! \ change BASE to hexadecimal
1199 CR ." $" 2 U.R \ print IR_RC5 code
1200 ['] (CR) IS CR \ restore CR
1201 ['] (EMIT) IS EMIT \ restore EMIT
1202 HI2LO \ switch from FORTH to assembler
1203 \ ------------------------------\
1204 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
1205 \ ------------------------------\
1206 MOV @PSP+,&BASE \ restore variable BASE
1207 RETI \ CPU is ON, GIE is OFF
1212 \ ------------------------------\
1213 \ TB0CTL = %0000 0010 1001 0100\$3C0
1214 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1215 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1216 \ -- \ID input divider \ 10 = /4
1217 \ -- \MC Mode Control \ 01 = up to TB0CCR0
1218 \ - \TBCLR TimerB Clear
1221 \ --------------------------------\\
1222 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1223 \ -- \CM Capture Mode
1228 \ --- \OUTMOD \ 011 = set/reset
1234 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
1236 \ ------------------------------\
1237 \ set TimerB to make 50kHz PWM \
1238 \ ------------------------------\
1239 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1240 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
1241 \ ------------------------------\
1242 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1243 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
1244 \ ------------------------------\
1245 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1246 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
1247 \ ------------------------------\
1248 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1249 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
1250 \ ------------------------------\
1251 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1252 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
1253 \ ------------------------------\
1254 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
1255 \ ------------------------------\
1256 \ set TimerB to generate PWM for LCD_Vo
1257 \ ------------------------------\
1258 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
1259 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
1260 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1261 \ ------------------------------\
1262 BIS.B #LCDVo,&LCDVo_DIR \
1263 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
1264 \ ------------------------------\
1265 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1266 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1267 \ ------------------------------\
1268 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1269 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1270 \ ------------------------------\
1271 \ WDT interval init part \
1272 \ ------------------------------\
1273 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
1274 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
1275 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
1276 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
1277 \ ------------------------------\
1279 \ ------------------------------\
1280 BIS.B #RC5,&IR_IE \ enable RC5_Int
1281 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1282 \ ------------------------------\
1283 \ init interrupt vectors
1284 \ ------------------------------\
1285 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
1286 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1287 \ ------------------------------\
1288 \ define LPM mode for ACCEPT \
1289 \ ------------------------------\
1290 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1291 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1292 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1294 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
1296 \ ------------------------------\
1298 \ ------------------------------\
1299 $03E8 20_US \ 1- wait 20 ms
1300 $03 TOP_LCD \ 2- send DB5=DB4=1
1301 $CD 20_US \ 3- wait 4,1 ms
1302 $03 TOP_LCD \ 4- send again DB5=DB4=1
1303 $5 20_US \ 5- wait 0,1 ms
1304 $03 TOP_LCD \ 6- send again again DB5=DB4=1
1305 $2 20_US \ wait 40 us = LCD cycle
1306 $02 TOP_LCD \ 7- send DB5=1 DB4=0
1307 $2 20_US \ wait 40 us = LCD cycle
1308 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1309 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1310 LCD_Clear \ 10- "LCD_Clear"
1311 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1312 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1313 LCD_Clear \ 10- "LCD_Clear"
1314 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1315 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1317 ['] (CR) IS CR \ ' (CR) is CR
1318 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
1320 ." RC5toLCD is running. Type STOP to quit"
1321 \ NOECHO \ uncomment to run this app without terminal connexion
1322 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
1323 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
1327 : STOP \ stops multitasking, must to be used before downloading app
1328 ['] (WARM) IS WARM \ remove START app from FORTH init process
1329 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
1337 CODE MAX \ n1 n2 -- n3 signed maximum
1338 CMP @PSP,TOS \ n2-n1
1339 S< ?GOTO FW1 \ n2<n1
1345 CODE MIN \ n1 n2 -- n3 signed minimum
1346 CMP @PSP,TOS \ n2-n1
1347 S< ?GOTO BW1 \ n2<n1
1353 : U.R \ u n -- display u unsigned in n width (n >= 2)
1355 R> OVER - 0 MAX SPACES TYPE
1359 CODE 20_US \ n -- n * 20 us
1360 BEGIN \ 3 cycles loop + 6~
1361 \ MOV #5,W \ 3 MCLK = 1 MHz
1362 \ MOV #23,W \ 3 MCLK = 4 MHz
1363 MOV #51,W \ 3 MCLK = 8 MHz
1364 \ MOV #104,W \ 3 MCLK = 16 MHz
1365 \ MOV #158,W \ 3 MCLK = 24 MHz
1366 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
1376 CODE TOP_LCD \ LCD Sample
1377 \ \ if write : %xxxxWWWW --
1378 \ \ if read : -- %0000RRRR
1379 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1380 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1381 0= IF \ write LCD bits pattern
1383 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1384 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1387 THEN \ read LCD bits pattern
1390 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1391 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1397 CODE LCD_W \ byte -- write byte to LCD
1399 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1400 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1401 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1402 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1403 COLON \ high level word starts here
1404 TOP_LCD 2 20_US \ write high nibble first
1409 CODE LCD_WrC \ char -- Write Char
1410 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1415 CODE LCD_WrF \ func -- Write Fonction
1416 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1422 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1427 $02 LCD_WrF 100 20_us
1431 \ : LCD_Entry_set $04 OR LCD_WrF ;
1433 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1435 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1437 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1439 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1441 \ : LCD_Goto $80 OR LCD_WrF ;
1443 \ CODE LCD_R \ -- byte read byte from LCD
1444 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1445 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1446 \ COLON \ starts a FORTH word
1447 \ TOP_LCD 2 20_us \ -- %0000HHHH
1448 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1449 \ HI2LO \ switch from FORTH to assembler
1450 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1451 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1452 \ MOV @RSP+,IP \ restore IP saved by COLON
1457 \ CODE LCD_RdS \ -- status Read Status
1458 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1463 \ CODE LCD_RdC \ -- char Read Char
1464 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1469 \ -------------+------+------+------+------++---+---+---+---+---------+
1470 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1471 \ -------------+------+------+------+------++---+---+---+---+---------+
1472 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1473 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1474 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1475 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1476 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1477 \ -------------+------+------+------+------++---+---+---+---+---------+
1480 \ ******************************\
1481 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1482 \ ******************************\
1483 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1484 \ ------------------------------\
1485 \ define LPM mode for ACCEPT \
1486 \ ------------------------------\
1487 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1488 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1489 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1490 BIT.B #SW2,&SW2_IN \ test switch S2
1491 0= IF \ case of switch S2 pressed
1492 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1494 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1497 BIT.B #SW1,&SW1_IN \ test switch S1 input
1498 0= IF \ case of Switch S1 pressed
1499 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1501 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1505 RETI \ CPU is ON, GIE is OFF
1510 \ ------------------------------\
1511 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1512 \ ******************************\
1513 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1514 \ ******************************\
1515 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1516 \ \ SMclock = 8|16|24 MHz
1517 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1518 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1519 \ \ SR(9)=new Toggle bit memory (ADD on)
1520 \ ------------------------------\
1521 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1522 \ ------------------------------\
1523 \ define LPM mode for ACCEPT \
1524 \ ------------------------------\
1525 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1526 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1527 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1528 \ ------------------------------\
1529 \ RC5_FirstStartBitHalfCycle: \
1530 \ ------------------------------\
1531 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1532 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1533 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1534 MOV #1778,X \ RC5_Period in us
1535 MOV #14,W \ count of loop
1537 \ ------------------------------\
1538 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1539 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1540 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1541 \ RC5_Compute_3/4_Period: \ |
1542 RRUM #1,X \ X=1/2 cycle |
1546 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1547 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1549 \ ------------------------------\
1550 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1551 \ ------------------------------\
1552 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1553 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1554 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1555 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1556 SUB #1,W \ decrement count loop
1557 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1558 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1559 0<> WHILE \ ----> out of loop ----+
1560 \ RC5_compute_7/4_Time_out: \ |
1561 ADD X,Y \ | out of bound = 7/4 period
1562 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1564 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1565 0>= IF \ | if cycle time out of bound
1566 BIC #$30,&TA0CTL \ | stop timer_A0
1567 RETI \ | then quit to do nothing
1569 \ ------------------------------\ |
1570 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1572 MOV &TA0R,X \ | | get new RC5_period value
1573 REPEAT \ ----> loop back --+ |
1574 \ ------------------------------\ |
1575 \ RC5_SampleEndOf: \ <---------------------+
1576 \ ------------------------------\
1577 BIC #$30,&TA0CTL \ stop timer_A0
1578 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1579 \ ******************************\
1580 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1581 \ ******************************\
1582 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
1583 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
1584 XOR IP,X \ (new XOR old) Toggle bit (13)
1585 BIT #BIT13,X \ X(13) = New_RC5_command
1586 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
1588 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
1589 \ ******************************\
1590 \ RC5_ComputeNewRC5word \
1591 \ ******************************\
1593 MOV &BASE,2(PSP) \ save variable BASE before use
1594 MOV TOS,0(PSP) \ save TOS before use
1595 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
1596 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
1597 \ ******************************\
1598 \ RC5_ComputeC6bit \
1599 \ ******************************\
1600 BIT #$4000,IP \ test /C6 bit in IP
1601 0= IF BIS #$40,TOS \ set C6 bit in S
1602 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
1603 \ ******************************\
1604 \ RC5_CommandByteIsDone \ RC5_code --
1605 \ ******************************\
1607 \ ------------------------------\
1608 \ Display IR_RC5 code \
1609 \ ------------------------------\
1610 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
1611 \ ------------------------------\
1612 LO2HI \ switch from assembler to FORTH
1613 ['] LCD_CLEAR IS CR \ redirects CR
1614 ['] LCD_WrC IS EMIT \ redirects EMIT
1615 $10 BASE ! \ change BASE to hexadecimal
1616 CR ." $" 2 U.R \ print IR_RC5 code
1617 ['] (CR) IS CR \ restore CR
1618 ['] (EMIT) IS EMIT \ restore EMIT
1619 HI2LO \ switch from FORTH to assembler
1620 \ ------------------------------\
1621 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
1622 \ ------------------------------\
1623 MOV @PSP+,&BASE \ restore variable BASE
1624 RETI \ CPU is ON, GIE is OFF
1629 \ ------------------------------\
1630 \ TB0CTL = %0000 0010 1001 0100\$3C0
1631 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1632 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1633 \ -- \ID input divider \ 10 = /4
1634 \ -- \MC Mode Control \ 01 = up to TB0CCR0
1635 \ - \TBCLR TimerB Clear
1638 \ --------------------------------\\
1639 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1640 \ -- \CM Capture Mode
1645 \ --- \OUTMOD \ 011 = set/reset
1651 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
1653 \ ------------------------------\
1654 \ set TimerB to make 50kHz PWM \
1655 \ ------------------------------\
1656 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1657 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
1658 \ ------------------------------\
1659 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1660 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
1661 \ ------------------------------\
1662 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1663 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
1664 \ ------------------------------\
1665 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1666 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
1667 \ ------------------------------\
1668 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1669 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
1670 \ ------------------------------\
1671 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
1672 \ ------------------------------\
1673 \ set TimerB to generate PWM for LCD_Vo
1674 \ ------------------------------\
1675 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
1676 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
1677 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1678 \ ------------------------------\
1679 BIS.B #LCDVo,&LCDVo_DIR \
1680 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
1681 \ ------------------------------\
1682 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1683 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1684 \ ------------------------------\
1685 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1686 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1687 \ ------------------------------\
1688 \ WDT interval init part \
1689 \ ------------------------------\
1690 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
1691 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
1692 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
1693 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
1694 \ ------------------------------\
1696 \ ------------------------------\
1697 BIS.B #RC5,&IR_IE \ enable RC5_Int
1698 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1699 \ ------------------------------\
1700 \ init interrupt vectors
1701 \ ------------------------------\
1702 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
1703 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1704 \ ------------------------------\
1705 \ define LPM mode for ACCEPT \
1706 \ ------------------------------\
1707 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1708 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1709 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1711 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
1713 \ ------------------------------\
1715 \ ------------------------------\
1716 $03E8 20_US \ 1- wait 20 ms
1717 $03 TOP_LCD \ 2- send DB5=DB4=1
1718 $CD 20_US \ 3- wait 4,1 ms
1719 $03 TOP_LCD \ 4- send again DB5=DB4=1
1720 $5 20_US \ 5- wait 0,1 ms
1721 $03 TOP_LCD \ 6- send again again DB5=DB4=1
1722 $2 20_US \ wait 40 us = LCD cycle
1723 $02 TOP_LCD \ 7- send DB5=1 DB4=0
1724 $2 20_US \ wait 40 us = LCD cycle
1725 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1726 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1727 LCD_Clear \ 10- "LCD_Clear"
1728 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1729 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1730 LCD_Clear \ 10- "LCD_Clear"
1731 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1732 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1734 ['] (CR) IS CR \ ' (CR) is CR
1735 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
1737 ." RC5toLCD is running. Type STOP to quit"
1738 \ NOECHO \ uncomment to run this app without terminal connexion
1739 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
1740 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
1744 : STOP \ stops multitasking, must to be used before downloading app
1745 ['] (WARM) IS WARM \ remove START app from FORTH init process
1746 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
1754 CODE MAX \ n1 n2 -- n3 signed maximum
1755 CMP @PSP,TOS \ n2-n1
1756 S< ?GOTO FW1 \ n2<n1
1762 CODE MIN \ n1 n2 -- n3 signed minimum
1763 CMP @PSP,TOS \ n2-n1
1764 S< ?GOTO BW1 \ n2<n1
1770 : U.R \ u n -- display u unsigned in n width (n >= 2)
1772 R> OVER - 0 MAX SPACES TYPE
1776 CODE 20_US \ n -- n * 20 us
1777 BEGIN \ 3 cycles loop + 6~
1778 \ MOV #5,W \ 3 MCLK = 1 MHz
1779 \ MOV #23,W \ 3 MCLK = 4 MHz
1780 MOV #51,W \ 3 MCLK = 8 MHz
1781 \ MOV #104,W \ 3 MCLK = 16 MHz
1782 \ MOV #158,W \ 3 MCLK = 24 MHz
1783 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
1793 CODE TOP_LCD \ LCD Sample
1794 \ \ if write : %xxxxWWWW --
1795 \ \ if read : -- %0000RRRR
1796 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1797 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1798 0= IF \ write LCD bits pattern
1800 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1801 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1804 THEN \ read LCD bits pattern
1807 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1808 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1814 CODE LCD_W \ byte -- write byte to LCD
1816 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1817 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1818 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1819 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1820 COLON \ high level word starts here
1821 TOP_LCD 2 20_US \ write high nibble first
1826 CODE LCD_WrC \ char -- Write Char
1827 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1832 CODE LCD_WrF \ func -- Write Fonction
1833 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1839 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1844 $02 LCD_WrF 100 20_us
1848 \ : LCD_Entry_set $04 OR LCD_WrF ;
1850 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1852 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1854 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1856 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1858 \ : LCD_Goto $80 OR LCD_WrF ;
1860 \ CODE LCD_R \ -- byte read byte from LCD
1861 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1862 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1863 \ COLON \ starts a FORTH word
1864 \ TOP_LCD 2 20_us \ -- %0000HHHH
1865 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1866 \ HI2LO \ switch from FORTH to assembler
1867 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1868 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1869 \ MOV @RSP+,IP \ restore IP saved by COLON
1874 \ CODE LCD_RdS \ -- status Read Status
1875 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1880 \ CODE LCD_RdC \ -- char Read Char
1881 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1886 \ -------------+------+------+------+------++---+---+---+---+---------+
1887 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1888 \ -------------+------+------+------+------++---+---+---+---+---------+
1889 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1890 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1891 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1892 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1893 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1894 \ -------------+------+------+------+------++---+---+---+---+---------+
1897 \ ******************************\
1898 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1899 \ ******************************\
1900 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1901 \ ------------------------------\
1902 \ define LPM mode for ACCEPT \
1903 \ ------------------------------\
1904 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1905 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1906 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1907 BIT.B #SW2,&SW2_IN \ test switch S2
1908 0= IF \ case of switch S2 pressed
1909 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1911 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1914 BIT.B #SW1,&SW1_IN \ test switch S1 input
1915 0= IF \ case of Switch S1 pressed
1916 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1918 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1922 RETI \ CPU is ON, GIE is OFF
1927 \ ------------------------------\
1928 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1929 \ ******************************\
1930 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1931 \ ******************************\
1932 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1933 \ \ SMclock = 8|16|24 MHz
1934 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1935 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1936 \ \ SR(9)=new Toggle bit memory (ADD on)
1937 \ ------------------------------\
1938 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1939 \ ------------------------------\
1940 \ define LPM mode for ACCEPT \
1941 \ ------------------------------\
1942 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1943 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1944 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1945 \ ------------------------------\
1946 \ RC5_FirstStartBitHalfCycle: \
1947 \ ------------------------------\
1948 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1949 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1950 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1951 MOV #1778,X \ RC5_Period in us
1952 MOV #14,W \ count of loop
1954 \ ------------------------------\
1955 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1956 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1957 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1958 \ RC5_Compute_3/4_Period: \ |
1959 RRUM #1,X \ X=1/2 cycle |
1963 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1964 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1966 \ ------------------------------\
1967 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1968 \ ------------------------------\
1969 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1970 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1971 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1972 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1973 SUB #1,W \ decrement count loop
1974 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1975 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1976 0<> WHILE \ ----> out of loop ----+
1977 \ RC5_compute_7/4_Time_out: \ |
1978 ADD X,Y \ | out of bound = 7/4 period
1979 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1981 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1982 0>= IF \ | if cycle time out of bound
1983 BIC #$30,&TA0CTL \ | stop timer_A0
1984 RETI \ | then quit to do nothing
1986 \ ------------------------------\ |
1987 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1989 MOV &TA0R,X \ | | get new RC5_period value
1990 REPEAT \ ----> loop back --+ |
1991 \ ------------------------------\ |
1992 \ RC5_SampleEndOf: \ <---------------------+
1993 \ ------------------------------\
1994 BIC #$30,&TA0CTL \ stop timer_A0
1995 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1996 \ ******************************\
1997 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1998 \ ******************************\
1999 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
2000 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2001 XOR IP,X \ (new XOR old) Toggle bit (13)
2002 BIT #BIT13,X \ X(13) = New_RC5_command
2003 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2005 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2006 \ ******************************\
2007 \ RC5_ComputeNewRC5word \
2008 \ ******************************\
2010 MOV &BASE,2(PSP) \ save variable BASE before use
2011 MOV TOS,0(PSP) \ save TOS before use
2012 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2013 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2014 \ ******************************\
2015 \ RC5_ComputeC6bit \
2016 \ ******************************\
2017 BIT #$4000,IP \ test /C6 bit in IP
2018 0= IF BIS #$40,TOS \ set C6 bit in S
2019 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2020 \ ******************************\
2021 \ RC5_CommandByteIsDone \ RC5_code --
2022 \ ******************************\
2024 \ ------------------------------\
2025 \ Display IR_RC5 code \
2026 \ ------------------------------\
2027 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2028 \ ------------------------------\
2029 LO2HI \ switch from assembler to FORTH
2030 ['] LCD_CLEAR IS CR \ redirects CR
2031 ['] LCD_WrC IS EMIT \ redirects EMIT
2032 $10 BASE ! \ change BASE to hexadecimal
2033 CR ." $" 2 U.R \ print IR_RC5 code
2034 ['] (CR) IS CR \ restore CR
2035 ['] (EMIT) IS EMIT \ restore EMIT
2036 HI2LO \ switch from FORTH to assembler
2037 \ ------------------------------\
2038 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2039 \ ------------------------------\
2040 MOV @PSP+,&BASE \ restore variable BASE
2041 RETI \ CPU is ON, GIE is OFF
2046 \ ------------------------------\
2047 \ TB0CTL = %0000 0010 1001 0100\$3C0
2048 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2049 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2050 \ -- \ID input divider \ 10 = /4
2051 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2052 \ - \TBCLR TimerB Clear
2055 \ --------------------------------\\
2056 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2057 \ -- \CM Capture Mode
2062 \ --- \OUTMOD \ 011 = set/reset
2068 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2070 \ ------------------------------\
2071 \ set TimerB to make 50kHz PWM \
2072 \ ------------------------------\
2073 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2074 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2075 \ ------------------------------\
2076 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2077 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2078 \ ------------------------------\
2079 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2080 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2081 \ ------------------------------\
2082 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2083 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2084 \ ------------------------------\
2085 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2086 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2087 \ ------------------------------\
2088 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2089 \ ------------------------------\
2090 \ set TimerB to generate PWM for LCD_Vo
2091 \ ------------------------------\
2092 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2093 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2094 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2095 \ ------------------------------\
2096 BIS.B #LCDVo,&LCDVo_DIR \
2097 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2098 \ ------------------------------\
2099 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2100 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2101 \ ------------------------------\
2102 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2103 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2104 \ ------------------------------\
2105 \ WDT interval init part \
2106 \ ------------------------------\
2107 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2108 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2109 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2110 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2111 \ ------------------------------\
2113 \ ------------------------------\
2114 BIS.B #RC5,&IR_IE \ enable RC5_Int
2115 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2116 \ ------------------------------\
2117 \ init interrupt vectors
2118 \ ------------------------------\
2119 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2120 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2121 \ ------------------------------\
2122 \ define LPM mode for ACCEPT \
2123 \ ------------------------------\
2124 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2125 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2126 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2128 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2130 \ ------------------------------\
2132 \ ------------------------------\
2133 $03E8 20_US \ 1- wait 20 ms
2134 $03 TOP_LCD \ 2- send DB5=DB4=1
2135 $CD 20_US \ 3- wait 4,1 ms
2136 $03 TOP_LCD \ 4- send again DB5=DB4=1
2137 $5 20_US \ 5- wait 0,1 ms
2138 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2139 $2 20_US \ wait 40 us = LCD cycle
2140 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2141 $2 20_US \ wait 40 us = LCD cycle
2142 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2143 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2144 LCD_Clear \ 10- "LCD_Clear"
2145 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2146 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2147 LCD_Clear \ 10- "LCD_Clear"
2148 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2149 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2151 ['] (CR) IS CR \ ' (CR) is CR
2152 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2154 ." RC5toLCD is running. Type STOP to quit"
2155 \ NOECHO \ uncomment to run this app without terminal connexion
2156 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2157 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2161 : STOP \ stops multitasking, must to be used before downloading app
2162 ['] (WARM) IS WARM \ remove START app from FORTH init process
2163 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
2171 CODE MAX \ n1 n2 -- n3 signed maximum
2172 CMP @PSP,TOS \ n2-n1
2173 S< ?GOTO FW1 \ n2<n1
2179 CODE MIN \ n1 n2 -- n3 signed minimum
2180 CMP @PSP,TOS \ n2-n1
2181 S< ?GOTO BW1 \ n2<n1
2187 : U.R \ u n -- display u unsigned in n width (n >= 2)
2189 R> OVER - 0 MAX SPACES TYPE
2193 CODE 20_US \ n -- n * 20 us
2194 BEGIN \ 3 cycles loop + 6~
2195 \ MOV #5,W \ 3 MCLK = 1 MHz
2196 \ MOV #23,W \ 3 MCLK = 4 MHz
2197 MOV #51,W \ 3 MCLK = 8 MHz
2198 \ MOV #104,W \ 3 MCLK = 16 MHz
2199 \ MOV #158,W \ 3 MCLK = 24 MHz
2200 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
2210 CODE TOP_LCD \ LCD Sample
2211 \ \ if write : %xxxxWWWW --
2212 \ \ if read : -- %0000RRRR
2213 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2214 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2215 0= IF \ write LCD bits pattern
2217 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2218 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2221 THEN \ read LCD bits pattern
2224 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2225 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2231 CODE LCD_W \ byte -- write byte to LCD
2233 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2234 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2235 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2236 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2237 COLON \ high level word starts here
2238 TOP_LCD 2 20_US \ write high nibble first
2243 CODE LCD_WrC \ char -- Write Char
2244 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2249 CODE LCD_WrF \ func -- Write Fonction
2250 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2256 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
2261 $02 LCD_WrF 100 20_us
2265 \ : LCD_Entry_set $04 OR LCD_WrF ;
2267 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
2269 \ : LCD_Display_Shift $10 OR LCD_WrF ;
2271 \ : LCD_Fn_Set $20 OR LCD_WrF ;
2273 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
2275 \ : LCD_Goto $80 OR LCD_WrF ;
2277 \ CODE LCD_R \ -- byte read byte from LCD
2278 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2279 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2280 \ COLON \ starts a FORTH word
2281 \ TOP_LCD 2 20_us \ -- %0000HHHH
2282 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2283 \ HI2LO \ switch from FORTH to assembler
2284 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2285 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2286 \ MOV @RSP+,IP \ restore IP saved by COLON
2291 \ CODE LCD_RdS \ -- status Read Status
2292 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2297 \ CODE LCD_RdC \ -- char Read Char
2298 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2303 \ -------------+------+------+------+------++---+---+---+---+---------+
2304 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
2305 \ -------------+------+------+------+------++---+---+---+---+---------+
2306 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
2307 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
2308 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
2309 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
2310 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
2311 \ -------------+------+------+------+------++---+---+---+---+---------+
2314 \ ******************************\
2315 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2316 \ ******************************\
2317 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
2318 \ ------------------------------\
2319 \ define LPM mode for ACCEPT \
2320 \ ------------------------------\
2321 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2322 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2323 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2324 BIT.B #SW2,&SW2_IN \ test switch S2
2325 0= IF \ case of switch S2 pressed
2326 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
2328 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
2331 BIT.B #SW1,&SW1_IN \ test switch S1 input
2332 0= IF \ case of Switch S1 pressed
2333 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
2335 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
2339 RETI \ CPU is ON, GIE is OFF
2344 \ ------------------------------\
2345 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2346 \ ******************************\
2347 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2348 \ ******************************\
2349 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2350 \ \ SMclock = 8|16|24 MHz
2351 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
2352 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
2353 \ \ SR(9)=new Toggle bit memory (ADD on)
2354 \ ------------------------------\
2355 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
2356 \ ------------------------------\
2357 \ define LPM mode for ACCEPT \
2358 \ ------------------------------\
2359 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2360 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2361 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2362 \ ------------------------------\
2363 \ RC5_FirstStartBitHalfCycle: \
2364 \ ------------------------------\
2365 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
2366 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
2367 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
2368 MOV #1778,X \ RC5_Period in us
2369 MOV #14,W \ count of loop
2371 \ ------------------------------\
2372 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
2373 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
2374 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
2375 \ RC5_Compute_3/4_Period: \ |
2376 RRUM #1,X \ X=1/2 cycle |
2380 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
2381 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
2383 \ ------------------------------\
2384 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
2385 \ ------------------------------\
2386 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2387 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
2388 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2389 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2390 SUB #1,W \ decrement count loop
2391 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
2392 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2393 0<> WHILE \ ----> out of loop ----+
2394 \ RC5_compute_7/4_Time_out: \ |
2395 ADD X,Y \ | out of bound = 7/4 period
2396 \ RC5_WaitHalfCycleP1.2_IFG: \ |
2398 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
2399 0>= IF \ | if cycle time out of bound
2400 BIC #$30,&TA0CTL \ | stop timer_A0
2401 RETI \ | then quit to do nothing
2403 \ ------------------------------\ |
2404 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
2406 MOV &TA0R,X \ | | get new RC5_period value
2407 REPEAT \ ----> loop back --+ |
2408 \ ------------------------------\ |
2409 \ RC5_SampleEndOf: \ <---------------------+
2410 \ ------------------------------\
2411 BIC #$30,&TA0CTL \ stop timer_A0
2412 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2413 \ ******************************\
2414 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2415 \ ******************************\
2416 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
2417 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2418 XOR IP,X \ (new XOR old) Toggle bit (13)
2419 BIT #BIT13,X \ X(13) = New_RC5_command
2420 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2422 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2423 \ ******************************\
2424 \ RC5_ComputeNewRC5word \
2425 \ ******************************\
2427 MOV &BASE,2(PSP) \ save variable BASE before use
2428 MOV TOS,0(PSP) \ save TOS before use
2429 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2430 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2431 \ ******************************\
2432 \ RC5_ComputeC6bit \
2433 \ ******************************\
2434 BIT #$4000,IP \ test /C6 bit in IP
2435 0= IF BIS #$40,TOS \ set C6 bit in S
2436 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2437 \ ******************************\
2438 \ RC5_CommandByteIsDone \ RC5_code --
2439 \ ******************************\
2441 \ ------------------------------\
2442 \ Display IR_RC5 code \
2443 \ ------------------------------\
2444 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2445 \ ------------------------------\
2446 LO2HI \ switch from assembler to FORTH
2447 ['] LCD_CLEAR IS CR \ redirects CR
2448 ['] LCD_WrC IS EMIT \ redirects EMIT
2449 $10 BASE ! \ change BASE to hexadecimal
2450 CR ." $" 2 U.R \ print IR_RC5 code
2451 ['] (CR) IS CR \ restore CR
2452 ['] (EMIT) IS EMIT \ restore EMIT
2453 HI2LO \ switch from FORTH to assembler
2454 \ ------------------------------\
2455 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2456 \ ------------------------------\
2457 MOV @PSP+,&BASE \ restore variable BASE
2458 RETI \ CPU is ON, GIE is OFF
2463 \ ------------------------------\
2464 \ TB0CTL = %0000 0010 1001 0100\$3C0
2465 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2466 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2467 \ -- \ID input divider \ 10 = /4
2468 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2469 \ - \TBCLR TimerB Clear
2472 \ --------------------------------\\
2473 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2474 \ -- \CM Capture Mode
2479 \ --- \OUTMOD \ 011 = set/reset
2485 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2487 \ ------------------------------\
2488 \ set TimerB to make 50kHz PWM \
2489 \ ------------------------------\
2490 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2491 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2492 \ ------------------------------\
2493 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2494 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2495 \ ------------------------------\
2496 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2497 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2498 \ ------------------------------\
2499 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2500 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2501 \ ------------------------------\
2502 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2503 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2504 \ ------------------------------\
2505 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2506 \ ------------------------------\
2507 \ set TimerB to generate PWM for LCD_Vo
2508 \ ------------------------------\
2509 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2510 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2511 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2512 \ ------------------------------\
2513 BIS.B #LCDVo,&LCDVo_DIR \
2514 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2515 \ ------------------------------\
2516 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2517 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2518 \ ------------------------------\
2519 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2520 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2521 \ ------------------------------\
2522 \ WDT interval init part \
2523 \ ------------------------------\
2524 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2525 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2526 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2527 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2528 \ ------------------------------\
2530 \ ------------------------------\
2531 BIS.B #RC5,&IR_IE \ enable RC5_Int
2532 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2533 \ ------------------------------\
2534 \ init interrupt vectors
2535 \ ------------------------------\
2536 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2537 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2538 \ ------------------------------\
2539 \ define LPM mode for ACCEPT \
2540 \ ------------------------------\
2541 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2542 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2543 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2545 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2547 \ ------------------------------\
2549 \ ------------------------------\
2550 $03E8 20_US \ 1- wait 20 ms
2551 $03 TOP_LCD \ 2- send DB5=DB4=1
2552 $CD 20_US \ 3- wait 4,1 ms
2553 $03 TOP_LCD \ 4- send again DB5=DB4=1
2554 $5 20_US \ 5- wait 0,1 ms
2555 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2556 $2 20_US \ wait 40 us = LCD cycle
2557 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2558 $2 20_US \ wait 40 us = LCD cycle
2559 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2560 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2561 LCD_Clear \ 10- "LCD_Clear"
2562 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2563 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2564 LCD_Clear \ 10- "LCD_Clear"
2565 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2566 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2568 ['] (CR) IS CR \ ' (CR) is CR
2569 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2571 ." RC5toLCD is running. Type STOP to quit"
2572 \ NOECHO \ uncomment to run this app without terminal connexion
2573 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2574 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2578 : STOP \ stops multitasking, must to be used before downloading app
2579 ['] (WARM) IS WARM \ remove START app from FORTH init process
2580 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
2588 CODE MAX \ n1 n2 -- n3 signed maximum
2589 CMP @PSP,TOS \ n2-n1
2590 S< ?GOTO FW1 \ n2<n1
2596 CODE MIN \ n1 n2 -- n3 signed minimum
2597 CMP @PSP,TOS \ n2-n1
2598 S< ?GOTO BW1 \ n2<n1
2604 : U.R \ u n -- display u unsigned in n width (n >= 2)
2606 R> OVER - 0 MAX SPACES TYPE
2610 CODE 20_US \ n -- n * 20 us
2611 BEGIN \ 3 cycles loop + 6~
2612 \ MOV #5,W \ 3 MCLK = 1 MHz
2613 \ MOV #23,W \ 3 MCLK = 4 MHz
2614 MOV #51,W \ 3 MCLK = 8 MHz
2615 \ MOV #104,W \ 3 MCLK = 16 MHz
2616 \ MOV #158,W \ 3 MCLK = 24 MHz
2617 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
2627 CODE TOP_LCD \ LCD Sample
2628 \ \ if write : %xxxxWWWW --
2629 \ \ if read : -- %0000RRRR
2630 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2631 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2632 0= IF \ write LCD bits pattern
2634 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2635 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2638 THEN \ read LCD bits pattern
2641 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2642 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2648 CODE LCD_W \ byte -- write byte to LCD
2650 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2651 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2652 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2653 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2654 COLON \ high level word starts here
2655 TOP_LCD 2 20_US \ write high nibble first
2660 CODE LCD_WrC \ char -- Write Char
2661 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2666 CODE LCD_WrF \ func -- Write Fonction
2667 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2673 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
2678 $02 LCD_WrF 100 20_us
2682 \ : LCD_Entry_set $04 OR LCD_WrF ;
2684 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
2686 \ : LCD_Display_Shift $10 OR LCD_WrF ;
2688 \ : LCD_Fn_Set $20 OR LCD_WrF ;
2690 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
2692 \ : LCD_Goto $80 OR LCD_WrF ;
2694 \ CODE LCD_R \ -- byte read byte from LCD
2695 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2696 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2697 \ COLON \ starts a FORTH word
2698 \ TOP_LCD 2 20_us \ -- %0000HHHH
2699 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2700 \ HI2LO \ switch from FORTH to assembler
2701 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2702 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2703 \ MOV @RSP+,IP \ restore IP saved by COLON
2708 \ CODE LCD_RdS \ -- status Read Status
2709 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2714 \ CODE LCD_RdC \ -- char Read Char
2715 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2720 \ -------------+------+------+------+------++---+---+---+---+---------+
2721 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
2722 \ -------------+------+------+------+------++---+---+---+---+---------+
2723 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
2724 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
2725 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
2726 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
2727 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
2728 \ -------------+------+------+------+------++---+---+---+---+---------+
2731 \ ******************************\
2732 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2733 \ ******************************\
2734 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
2735 \ ------------------------------\
2736 \ define LPM mode for ACCEPT \
2737 \ ------------------------------\
2738 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2739 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2740 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2741 BIT.B #SW2,&SW2_IN \ test switch S2
2742 0= IF \ case of switch S2 pressed
2743 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
2745 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
2748 BIT.B #SW1,&SW1_IN \ test switch S1 input
2749 0= IF \ case of Switch S1 pressed
2750 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
2752 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
2756 RETI \ CPU is ON, GIE is OFF
2761 \ ------------------------------\
2762 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2763 \ ******************************\
2764 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2765 \ ******************************\
2766 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2767 \ \ SMclock = 8|16|24 MHz
2768 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
2769 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
2770 \ \ SR(9)=new Toggle bit memory (ADD on)
2771 \ ------------------------------\
2772 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
2773 \ ------------------------------\
2774 \ define LPM mode for ACCEPT \
2775 \ ------------------------------\
2776 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2777 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2778 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2779 \ ------------------------------\
2780 \ RC5_FirstStartBitHalfCycle: \
2781 \ ------------------------------\
2782 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
2783 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
2784 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
2785 MOV #1778,X \ RC5_Period in us
2786 MOV #14,W \ count of loop
2788 \ ------------------------------\
2789 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
2790 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
2791 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
2792 \ RC5_Compute_3/4_Period: \ |
2793 RRUM #1,X \ X=1/2 cycle |
2797 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
2798 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
2800 \ ------------------------------\
2801 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
2802 \ ------------------------------\
2803 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2804 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
2805 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2806 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2807 SUB #1,W \ decrement count loop
2808 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
2809 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2810 0<> WHILE \ ----> out of loop ----+
2811 \ RC5_compute_7/4_Time_out: \ |
2812 ADD X,Y \ | out of bound = 7/4 period
2813 \ RC5_WaitHalfCycleP1.2_IFG: \ |
2815 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
2816 0>= IF \ | if cycle time out of bound
2817 BIC #$30,&TA0CTL \ | stop timer_A0
2818 RETI \ | then quit to do nothing
2820 \ ------------------------------\ |
2821 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
2823 MOV &TA0R,X \ | | get new RC5_period value
2824 REPEAT \ ----> loop back --+ |
2825 \ ------------------------------\ |
2826 \ RC5_SampleEndOf: \ <---------------------+
2827 \ ------------------------------\
2828 BIC #$30,&TA0CTL \ stop timer_A0
2829 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2830 \ ******************************\
2831 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2832 \ ******************************\
2833 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
2834 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2835 XOR IP,X \ (new XOR old) Toggle bit (13)
2836 BIT #BIT13,X \ X(13) = New_RC5_command
2837 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2839 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2840 \ ******************************\
2841 \ RC5_ComputeNewRC5word \
2842 \ ******************************\
2844 MOV &BASE,2(PSP) \ save variable BASE before use
2845 MOV TOS,0(PSP) \ save TOS before use
2846 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2847 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2848 \ ******************************\
2849 \ RC5_ComputeC6bit \
2850 \ ******************************\
2851 BIT #$4000,IP \ test /C6 bit in IP
2852 0= IF BIS #$40,TOS \ set C6 bit in S
2853 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2854 \ ******************************\
2855 \ RC5_CommandByteIsDone \ RC5_code --
2856 \ ******************************\
2858 \ ------------------------------\
2859 \ Display IR_RC5 code \
2860 \ ------------------------------\
2861 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2862 \ ------------------------------\
2863 LO2HI \ switch from assembler to FORTH
2864 ['] LCD_CLEAR IS CR \ redirects CR
2865 ['] LCD_WrC IS EMIT \ redirects EMIT
2866 $10 BASE ! \ change BASE to hexadecimal
2867 CR ." $" 2 U.R \ print IR_RC5 code
2868 ['] (CR) IS CR \ restore CR
2869 ['] (EMIT) IS EMIT \ restore EMIT
2870 HI2LO \ switch from FORTH to assembler
2871 \ ------------------------------\
2872 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2873 \ ------------------------------\
2874 MOV @PSP+,&BASE \ restore variable BASE
2875 RETI \ CPU is ON, GIE is OFF
2880 \ ------------------------------\
2881 \ TB0CTL = %0000 0010 1001 0100\$3C0
2882 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2883 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2884 \ -- \ID input divider \ 10 = /4
2885 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2886 \ - \TBCLR TimerB Clear
2889 \ --------------------------------\\
2890 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2891 \ -- \CM Capture Mode
2896 \ --- \OUTMOD \ 011 = set/reset
2902 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2904 \ ------------------------------\
2905 \ set TimerB to make 50kHz PWM \
2906 \ ------------------------------\
2907 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2908 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2909 \ ------------------------------\
2910 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2911 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2912 \ ------------------------------\
2913 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2914 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2915 \ ------------------------------\
2916 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2917 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2918 \ ------------------------------\
2919 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2920 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2921 \ ------------------------------\
2922 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2923 \ ------------------------------\
2924 \ set TimerB to generate PWM for LCD_Vo
2925 \ ------------------------------\
2926 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2927 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2928 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2929 \ ------------------------------\
2930 BIS.B #LCDVo,&LCDVo_DIR \
2931 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2932 \ ------------------------------\
2933 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2934 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2935 \ ------------------------------\
2936 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2937 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2938 \ ------------------------------\
2939 \ WDT interval init part \
2940 \ ------------------------------\
2941 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2942 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2943 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2944 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2945 \ ------------------------------\
2947 \ ------------------------------\
2948 BIS.B #RC5,&IR_IE \ enable RC5_Int
2949 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2950 \ ------------------------------\
2951 \ init interrupt vectors
2952 \ ------------------------------\
2953 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2954 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2955 \ ------------------------------\
2956 \ define LPM mode for ACCEPT \
2957 \ ------------------------------\
2958 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2959 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2960 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2962 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2964 \ ------------------------------\
2966 \ ------------------------------\
2967 $03E8 20_US \ 1- wait 20 ms
2968 $03 TOP_LCD \ 2- send DB5=DB4=1
2969 $CD 20_US \ 3- wait 4,1 ms
2970 $03 TOP_LCD \ 4- send again DB5=DB4=1
2971 $5 20_US \ 5- wait 0,1 ms
2972 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2973 $2 20_US \ wait 40 us = LCD cycle
2974 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2975 $2 20_US \ wait 40 us = LCD cycle
2976 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2977 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2978 LCD_Clear \ 10- "LCD_Clear"
2979 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2980 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2981 LCD_Clear \ 10- "LCD_Clear"
2982 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2983 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2985 ['] (CR) IS CR \ ' (CR) is CR
2986 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2988 ." RC5toLCD is running. Type STOP to quit"
2989 \ NOECHO \ uncomment to run this app without terminal connexion
2990 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2991 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2995 : STOP \ stops multitasking, must to be used before downloading app
2996 ['] (WARM) IS WARM \ remove START app from FORTH init process
2997 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3005 CODE MAX \ n1 n2 -- n3 signed maximum
3006 CMP @PSP,TOS \ n2-n1
3007 S< ?GOTO FW1 \ n2<n1
3013 CODE MIN \ n1 n2 -- n3 signed minimum
3014 CMP @PSP,TOS \ n2-n1
3015 S< ?GOTO BW1 \ n2<n1
3021 : U.R \ u n -- display u unsigned in n width (n >= 2)
3023 R> OVER - 0 MAX SPACES TYPE
3027 CODE 20_US \ n -- n * 20 us
3028 BEGIN \ 3 cycles loop + 6~
3029 \ MOV #5,W \ 3 MCLK = 1 MHz
3030 \ MOV #23,W \ 3 MCLK = 4 MHz
3031 MOV #51,W \ 3 MCLK = 8 MHz
3032 \ MOV #104,W \ 3 MCLK = 16 MHz
3033 \ MOV #158,W \ 3 MCLK = 24 MHz
3034 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3044 CODE TOP_LCD \ LCD Sample
3045 \ \ if write : %xxxxWWWW --
3046 \ \ if read : -- %0000RRRR
3047 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3048 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3049 0= IF \ write LCD bits pattern
3051 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3052 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3055 THEN \ read LCD bits pattern
3058 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3059 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3065 CODE LCD_W \ byte -- write byte to LCD
3067 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3068 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3069 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3070 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3071 COLON \ high level word starts here
3072 TOP_LCD 2 20_US \ write high nibble first
3077 CODE LCD_WrC \ char -- Write Char
3078 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3083 CODE LCD_WrF \ func -- Write Fonction
3084 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3090 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3095 $02 LCD_WrF 100 20_us
3099 \ : LCD_Entry_set $04 OR LCD_WrF ;
3101 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3103 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3105 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3107 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3109 \ : LCD_Goto $80 OR LCD_WrF ;
3111 \ CODE LCD_R \ -- byte read byte from LCD
3112 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3113 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3114 \ COLON \ starts a FORTH word
3115 \ TOP_LCD 2 20_us \ -- %0000HHHH
3116 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3117 \ HI2LO \ switch from FORTH to assembler
3118 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3119 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3120 \ MOV @RSP+,IP \ restore IP saved by COLON
3125 \ CODE LCD_RdS \ -- status Read Status
3126 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3131 \ CODE LCD_RdC \ -- char Read Char
3132 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3137 \ -------------+------+------+------+------++---+---+---+---+---------+
3138 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3139 \ -------------+------+------+------+------++---+---+---+---+---------+
3140 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3141 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3142 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3143 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3144 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3145 \ -------------+------+------+------+------++---+---+---+---+---------+
3148 \ ******************************\
3149 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3150 \ ******************************\
3151 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3152 \ ------------------------------\
3153 \ define LPM mode for ACCEPT \
3154 \ ------------------------------\
3155 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3156 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3157 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3158 BIT.B #SW2,&SW2_IN \ test switch S2
3159 0= IF \ case of switch S2 pressed
3160 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
3162 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
3165 BIT.B #SW1,&SW1_IN \ test switch S1 input
3166 0= IF \ case of Switch S1 pressed
3167 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
3169 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
3173 RETI \ CPU is ON, GIE is OFF
3178 \ ------------------------------\
3179 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3180 \ ******************************\
3181 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3182 \ ******************************\
3183 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3184 \ \ SMclock = 8|16|24 MHz
3185 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
3186 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
3187 \ \ SR(9)=new Toggle bit memory (ADD on)
3188 \ ------------------------------\
3189 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
3190 \ ------------------------------\
3191 \ define LPM mode for ACCEPT \
3192 \ ------------------------------\
3193 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3194 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3195 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3196 \ ------------------------------\
3197 \ RC5_FirstStartBitHalfCycle: \
3198 \ ------------------------------\
3199 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
3200 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
3201 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
3202 MOV #1778,X \ RC5_Period in us
3203 MOV #14,W \ count of loop
3205 \ ------------------------------\
3206 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
3207 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
3208 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
3209 \ RC5_Compute_3/4_Period: \ |
3210 RRUM #1,X \ X=1/2 cycle |
3214 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
3215 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
3217 \ ------------------------------\
3218 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
3219 \ ------------------------------\
3220 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3221 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
3222 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3223 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3224 SUB #1,W \ decrement count loop
3225 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
3226 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3227 0<> WHILE \ ----> out of loop ----+
3228 \ RC5_compute_7/4_Time_out: \ |
3229 ADD X,Y \ | out of bound = 7/4 period
3230 \ RC5_WaitHalfCycleP1.2_IFG: \ |
3232 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
3233 0>= IF \ | if cycle time out of bound
3234 BIC #$30,&TA0CTL \ | stop timer_A0
3235 RETI \ | then quit to do nothing
3237 \ ------------------------------\ |
3238 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
3240 MOV &TA0R,X \ | | get new RC5_period value
3241 REPEAT \ ----> loop back --+ |
3242 \ ------------------------------\ |
3243 \ RC5_SampleEndOf: \ <---------------------+
3244 \ ------------------------------\
3245 BIC #$30,&TA0CTL \ stop timer_A0
3246 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
3247 \ ******************************\
3248 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3249 \ ******************************\
3250 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
3251 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
3252 XOR IP,X \ (new XOR old) Toggle bit (13)
3253 BIT #BIT13,X \ X(13) = New_RC5_command
3254 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
3256 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
3257 \ ******************************\
3258 \ RC5_ComputeNewRC5word \
3259 \ ******************************\
3261 MOV &BASE,2(PSP) \ save variable BASE before use
3262 MOV TOS,0(PSP) \ save TOS before use
3263 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
3264 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
3265 \ ******************************\
3266 \ RC5_ComputeC6bit \
3267 \ ******************************\
3268 BIT #$4000,IP \ test /C6 bit in IP
3269 0= IF BIS #$40,TOS \ set C6 bit in S
3270 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
3271 \ ******************************\
3272 \ RC5_CommandByteIsDone \ RC5_code --
3273 \ ******************************\
3275 \ ------------------------------\
3276 \ Display IR_RC5 code \
3277 \ ------------------------------\
3278 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
3279 \ ------------------------------\
3280 LO2HI \ switch from assembler to FORTH
3281 ['] LCD_CLEAR IS CR \ redirects CR
3282 ['] LCD_WrC IS EMIT \ redirects EMIT
3283 $10 BASE ! \ change BASE to hexadecimal
3284 CR ." $" 2 U.R \ print IR_RC5 code
3285 ['] (CR) IS CR \ restore CR
3286 ['] (EMIT) IS EMIT \ restore EMIT
3287 HI2LO \ switch from FORTH to assembler
3288 \ ------------------------------\
3289 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
3290 \ ------------------------------\
3291 MOV @PSP+,&BASE \ restore variable BASE
3292 RETI \ CPU is ON, GIE is OFF
3297 \ ------------------------------\
3298 \ TB0CTL = %0000 0010 1001 0100\$3C0
3299 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3300 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3301 \ -- \ID input divider \ 10 = /4
3302 \ -- \MC Mode Control \ 01 = up to TB0CCR0
3303 \ - \TBCLR TimerB Clear
3306 \ --------------------------------\\
3307 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3308 \ -- \CM Capture Mode
3313 \ --- \OUTMOD \ 011 = set/reset
3319 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
3321 \ ------------------------------\
3322 \ set TimerB to make 50kHz PWM \
3323 \ ------------------------------\
3324 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3325 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
3326 \ ------------------------------\
3327 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3328 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
3329 \ ------------------------------\
3330 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3331 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
3332 \ ------------------------------\
3333 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3334 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
3335 \ ------------------------------\
3336 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3337 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
3338 \ ------------------------------\
3339 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
3340 \ ------------------------------\
3341 \ set TimerB to generate PWM for LCD_Vo
3342 \ ------------------------------\
3343 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
3344 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
3345 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3346 \ ------------------------------\
3347 BIS.B #LCDVo,&LCDVo_DIR \
3348 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
3349 \ ------------------------------\
3350 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3351 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3352 \ ------------------------------\
3353 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3354 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3355 \ ------------------------------\
3356 \ WDT interval init part \
3357 \ ------------------------------\
3358 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
3359 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
3360 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
3361 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
3362 \ ------------------------------\
3364 \ ------------------------------\
3365 BIS.B #RC5,&IR_IE \ enable RC5_Int
3366 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3367 \ ------------------------------\
3368 \ init interrupt vectors
3369 \ ------------------------------\
3370 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
3371 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3372 \ ------------------------------\
3373 \ define LPM mode for ACCEPT \
3374 \ ------------------------------\
3375 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3376 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3377 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3379 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
3381 \ ------------------------------\
3383 \ ------------------------------\
3384 $03E8 20_US \ 1- wait 20 ms
3385 $03 TOP_LCD \ 2- send DB5=DB4=1
3386 $CD 20_US \ 3- wait 4,1 ms
3387 $03 TOP_LCD \ 4- send again DB5=DB4=1
3388 $5 20_US \ 5- wait 0,1 ms
3389 $03 TOP_LCD \ 6- send again again DB5=DB4=1
3390 $2 20_US \ wait 40 us = LCD cycle
3391 $02 TOP_LCD \ 7- send DB5=1 DB4=0
3392 $2 20_US \ wait 40 us = LCD cycle
3393 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3394 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3395 LCD_Clear \ 10- "LCD_Clear"
3396 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3397 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3398 LCD_Clear \ 10- "LCD_Clear"
3399 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3400 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3402 ['] (CR) IS CR \ ' (CR) is CR
3403 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
3405 ." RC5toLCD is running. Type STOP to quit"
3406 \ NOECHO \ uncomment to run this app without terminal connexion
3407 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
3408 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3412 : STOP \ stops multitasking, must to be used before downloading app
3413 ['] (WARM) IS WARM \ remove START app from FORTH init process
3414 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3422 CODE MAX \ n1 n2 -- n3 signed maximum
3423 CMP @PSP,TOS \ n2-n1
3424 S< ?GOTO FW1 \ n2<n1
3430 CODE MIN \ n1 n2 -- n3 signed minimum
3431 CMP @PSP,TOS \ n2-n1
3432 S< ?GOTO BW1 \ n2<n1
3438 : U.R \ u n -- display u unsigned in n width (n >= 2)
3440 R> OVER - 0 MAX SPACES TYPE
3444 CODE 20_US \ n -- n * 20 us
3445 BEGIN \ 3 cycles loop + 6~
3446 \ MOV #5,W \ 3 MCLK = 1 MHz
3447 \ MOV #23,W \ 3 MCLK = 4 MHz
3448 MOV #51,W \ 3 MCLK = 8 MHz
3449 \ MOV #104,W \ 3 MCLK = 16 MHz
3450 \ MOV #158,W \ 3 MCLK = 24 MHz
3451 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3461 CODE TOP_LCD \ LCD Sample
3462 \ \ if write : %xxxxWWWW --
3463 \ \ if read : -- %0000RRRR
3464 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3465 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3466 0= IF \ write LCD bits pattern
3468 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3469 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3472 THEN \ read LCD bits pattern
3475 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3476 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3482 CODE LCD_W \ byte -- write byte to LCD
3484 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3485 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3486 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3487 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3488 COLON \ high level word starts here
3489 TOP_LCD 2 20_US \ write high nibble first
3494 CODE LCD_WrC \ char -- Write Char
3495 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3500 CODE LCD_WrF \ func -- Write Fonction
3501 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3507 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3512 $02 LCD_WrF 100 20_us
3516 \ : LCD_Entry_set $04 OR LCD_WrF ;
3518 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3520 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3522 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3524 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3526 \ : LCD_Goto $80 OR LCD_WrF ;
3528 \ CODE LCD_R \ -- byte read byte from LCD
3529 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3530 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3531 \ COLON \ starts a FORTH word
3532 \ TOP_LCD 2 20_us \ -- %0000HHHH
3533 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3534 \ HI2LO \ switch from FORTH to assembler
3535 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3536 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3537 \ MOV @RSP+,IP \ restore IP saved by COLON
3542 \ CODE LCD_RdS \ -- status Read Status
3543 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3548 \ CODE LCD_RdC \ -- char Read Char
3549 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3554 \ -------------+------+------+------+------++---+---+---+---+---------+
3555 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3556 \ -------------+------+------+------+------++---+---+---+---+---------+
3557 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3558 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3559 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3560 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3561 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3562 \ -------------+------+------+------+------++---+---+---+---+---------+
3565 \ ******************************\
3566 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3567 \ ******************************\
3568 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3569 \ ------------------------------\
3570 \ define LPM mode for ACCEPT \
3571 \ ------------------------------\
3572 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3573 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3574 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3575 BIT.B #SW2,&SW2_IN \ test switch S2
3576 0= IF \ case of switch S2 pressed
3577 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
3579 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
3582 BIT.B #SW1,&SW1_IN \ test switch S1 input
3583 0= IF \ case of Switch S1 pressed
3584 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
3586 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
3590 RETI \ CPU is ON, GIE is OFF
3595 \ ------------------------------\
3596 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3597 \ ******************************\
3598 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3599 \ ******************************\
3600 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3601 \ \ SMclock = 8|16|24 MHz
3602 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
3603 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
3604 \ \ SR(9)=new Toggle bit memory (ADD on)
3605 \ ------------------------------\
3606 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
3607 \ ------------------------------\
3608 \ define LPM mode for ACCEPT \
3609 \ ------------------------------\
3610 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3611 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3612 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3613 \ ------------------------------\
3614 \ RC5_FirstStartBitHalfCycle: \
3615 \ ------------------------------\
3616 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
3617 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
3618 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
3619 MOV #1778,X \ RC5_Period in us
3620 MOV #14,W \ count of loop
3622 \ ------------------------------\
3623 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
3624 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
3625 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
3626 \ RC5_Compute_3/4_Period: \ |
3627 RRUM #1,X \ X=1/2 cycle |
3631 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
3632 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
3634 \ ------------------------------\
3635 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
3636 \ ------------------------------\
3637 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3638 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
3639 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3640 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3641 SUB #1,W \ decrement count loop
3642 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
3643 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3644 0<> WHILE \ ----> out of loop ----+
3645 \ RC5_compute_7/4_Time_out: \ |
3646 ADD X,Y \ | out of bound = 7/4 period
3647 \ RC5_WaitHalfCycleP1.2_IFG: \ |
3649 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
3650 0>= IF \ | if cycle time out of bound
3651 BIC #$30,&TA0CTL \ | stop timer_A0
3652 RETI \ | then quit to do nothing
3654 \ ------------------------------\ |
3655 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
3657 MOV &TA0R,X \ | | get new RC5_period value
3658 REPEAT \ ----> loop back --+ |
3659 \ ------------------------------\ |
3660 \ RC5_SampleEndOf: \ <---------------------+
3661 \ ------------------------------\
3662 BIC #$30,&TA0CTL \ stop timer_A0
3663 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
3664 \ ******************************\
3665 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3666 \ ******************************\
3667 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
3668 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
3669 XOR IP,X \ (new XOR old) Toggle bit (13)
3670 BIT #BIT13,X \ X(13) = New_RC5_command
3671 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
3673 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
3674 \ ******************************\
3675 \ RC5_ComputeNewRC5word \
3676 \ ******************************\
3678 MOV &BASE,2(PSP) \ save variable BASE before use
3679 MOV TOS,0(PSP) \ save TOS before use
3680 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
3681 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
3682 \ ******************************\
3683 \ RC5_ComputeC6bit \
3684 \ ******************************\
3685 BIT #$4000,IP \ test /C6 bit in IP
3686 0= IF BIS #$40,TOS \ set C6 bit in S
3687 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
3688 \ ******************************\
3689 \ RC5_CommandByteIsDone \ RC5_code --
3690 \ ******************************\
3692 \ ------------------------------\
3693 \ Display IR_RC5 code \
3694 \ ------------------------------\
3695 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
3696 \ ------------------------------\
3697 LO2HI \ switch from assembler to FORTH
3698 ['] LCD_CLEAR IS CR \ redirects CR
3699 ['] LCD_WrC IS EMIT \ redirects EMIT
3700 $10 BASE ! \ change BASE to hexadecimal
3701 CR ." $" 2 U.R \ print IR_RC5 code
3702 ['] (CR) IS CR \ restore CR
3703 ['] (EMIT) IS EMIT \ restore EMIT
3704 HI2LO \ switch from FORTH to assembler
3705 \ ------------------------------\
3706 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
3707 \ ------------------------------\
3708 MOV @PSP+,&BASE \ restore variable BASE
3709 RETI \ CPU is ON, GIE is OFF
3714 \ ------------------------------\
3715 \ TB0CTL = %0000 0010 1001 0100\$3C0
3716 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3717 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3718 \ -- \ID input divider \ 10 = /4
3719 \ -- \MC Mode Control \ 01 = up to TB0CCR0
3720 \ - \TBCLR TimerB Clear
3723 \ --------------------------------\\
3724 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3725 \ -- \CM Capture Mode
3730 \ --- \OUTMOD \ 011 = set/reset
3736 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
3738 \ ------------------------------\
3739 \ set TimerB to make 50kHz PWM \
3740 \ ------------------------------\
3741 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3742 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
3743 \ ------------------------------\
3744 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3745 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
3746 \ ------------------------------\
3747 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3748 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
3749 \ ------------------------------\
3750 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3751 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
3752 \ ------------------------------\
3753 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3754 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
3755 \ ------------------------------\
3756 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
3757 \ ------------------------------\
3758 \ set TimerB to generate PWM for LCD_Vo
3759 \ ------------------------------\
3760 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
3761 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
3762 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3763 \ ------------------------------\
3764 BIS.B #LCDVo,&LCDVo_DIR \
3765 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
3766 \ ------------------------------\
3767 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3768 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3769 \ ------------------------------\
3770 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3771 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3772 \ ------------------------------\
3773 \ WDT interval init part \
3774 \ ------------------------------\
3775 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
3776 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
3777 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
3778 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
3779 \ ------------------------------\
3781 \ ------------------------------\
3782 BIS.B #RC5,&IR_IE \ enable RC5_Int
3783 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3784 \ ------------------------------\
3785 \ init interrupt vectors
3786 \ ------------------------------\
3787 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
3788 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3789 \ ------------------------------\
3790 \ define LPM mode for ACCEPT \
3791 \ ------------------------------\
3792 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3793 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3794 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3796 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
3798 \ ------------------------------\
3800 \ ------------------------------\
3801 $03E8 20_US \ 1- wait 20 ms
3802 $03 TOP_LCD \ 2- send DB5=DB4=1
3803 $CD 20_US \ 3- wait 4,1 ms
3804 $03 TOP_LCD \ 4- send again DB5=DB4=1
3805 $5 20_US \ 5- wait 0,1 ms
3806 $03 TOP_LCD \ 6- send again again DB5=DB4=1
3807 $2 20_US \ wait 40 us = LCD cycle
3808 $02 TOP_LCD \ 7- send DB5=1 DB4=0
3809 $2 20_US \ wait 40 us = LCD cycle
3810 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3811 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3812 LCD_Clear \ 10- "LCD_Clear"
3813 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3814 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3815 LCD_Clear \ 10- "LCD_Clear"
3816 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3817 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3819 ['] (CR) IS CR \ ' (CR) is CR
3820 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
3822 ." RC5toLCD is running. Type STOP to quit"
3823 \ NOECHO \ uncomment to run this app without terminal connexion
3824 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
3825 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3829 : STOP \ stops multitasking, must to be used before downloading app
3830 ['] (WARM) IS WARM \ remove START app from FORTH init process
3831 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3839 CODE MAX \ n1 n2 -- n3 signed maximum
3840 CMP @PSP,TOS \ n2-n1
3841 S< ?GOTO FW1 \ n2<n1
3847 CODE MIN \ n1 n2 -- n3 signed minimum
3848 CMP @PSP,TOS \ n2-n1
3849 S< ?GOTO BW1 \ n2<n1
3855 : U.R \ u n -- display u unsigned in n width (n >= 2)
3857 R> OVER - 0 MAX SPACES TYPE
3861 CODE 20_US \ n -- n * 20 us
3862 BEGIN \ 3 cycles loop + 6~
3863 \ MOV #5,W \ 3 MCLK = 1 MHz
3864 \ MOV #23,W \ 3 MCLK = 4 MHz
3865 MOV #51,W \ 3 MCLK = 8 MHz
3866 \ MOV #104,W \ 3 MCLK = 16 MHz
3867 \ MOV #158,W \ 3 MCLK = 24 MHz
3868 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3878 CODE TOP_LCD \ LCD Sample
3879 \ \ if write : %xxxxWWWW --
3880 \ \ if read : -- %0000RRRR
3881 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3882 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3883 0= IF \ write LCD bits pattern
3885 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3886 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3889 THEN \ read LCD bits pattern
3892 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3893 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3899 CODE LCD_W \ byte -- write byte to LCD
3901 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3902 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3903 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3904 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3905 COLON \ high level word starts here
3906 TOP_LCD 2 20_US \ write high nibble first
3911 CODE LCD_WrC \ char -- Write Char
3912 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3917 CODE LCD_WrF \ func -- Write Fonction
3918 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3924 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3929 $02 LCD_WrF 100 20_us
3933 \ : LCD_Entry_set $04 OR LCD_WrF ;
3935 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3937 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3939 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3941 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3943 \ : LCD_Goto $80 OR LCD_WrF ;
3945 \ CODE LCD_R \ -- byte read byte from LCD
3946 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3947 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3948 \ COLON \ starts a FORTH word
3949 \ TOP_LCD 2 20_us \ -- %0000HHHH
3950 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3951 \ HI2LO \ switch from FORTH to assembler
3952 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3953 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3954 \ MOV @RSP+,IP \ restore IP saved by COLON
3959 \ CODE LCD_RdS \ -- status Read Status
3960 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3965 \ CODE LCD_RdC \ -- char Read Char
3966 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3971 \ -------------+------+------+------+------++---+---+---+---+---------+
3972 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3973 \ -------------+------+------+------+------++---+---+---+---+---------+
3974 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3975 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3976 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3977 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3978 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3979 \ -------------+------+------+------+------++---+---+---+---+---------+
3982 \ ******************************\
3983 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3984 \ ******************************\
3985 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3986 \ ------------------------------\
3987 \ define LPM mode for ACCEPT \
3988 \ ------------------------------\
3989 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3990 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3991 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3992 BIT.B #SW2,&SW2_IN \ test switch S2
3993 0= IF \ case of switch S2 pressed
3994 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
3996 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
3999 BIT.B #SW1,&SW1_IN \ test switch S1 input
4000 0= IF \ case of Switch S1 pressed
4001 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4003 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4007 RETI \ CPU is ON, GIE is OFF
4012 \ ------------------------------\
4013 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4014 \ ******************************\
4015 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4016 \ ******************************\
4017 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4018 \ \ SMclock = 8|16|24 MHz
4019 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4020 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4021 \ \ SR(9)=new Toggle bit memory (ADD on)
4022 \ ------------------------------\
4023 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4024 \ ------------------------------\
4025 \ define LPM mode for ACCEPT \
4026 \ ------------------------------\
4027 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4028 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4029 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4030 \ ------------------------------\
4031 \ RC5_FirstStartBitHalfCycle: \
4032 \ ------------------------------\
4033 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4034 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4035 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4036 MOV #1778,X \ RC5_Period in us
4037 MOV #14,W \ count of loop
4039 \ ------------------------------\
4040 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4041 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4042 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4043 \ RC5_Compute_3/4_Period: \ |
4044 RRUM #1,X \ X=1/2 cycle |
4048 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4049 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4051 \ ------------------------------\
4052 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4053 \ ------------------------------\
4054 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4055 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4056 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4057 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4058 SUB #1,W \ decrement count loop
4059 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4060 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4061 0<> WHILE \ ----> out of loop ----+
4062 \ RC5_compute_7/4_Time_out: \ |
4063 ADD X,Y \ | out of bound = 7/4 period
4064 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4066 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4067 0>= IF \ | if cycle time out of bound
4068 BIC #$30,&TA0CTL \ | stop timer_A0
4069 RETI \ | then quit to do nothing
4071 \ ------------------------------\ |
4072 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4074 MOV &TA0R,X \ | | get new RC5_period value
4075 REPEAT \ ----> loop back --+ |
4076 \ ------------------------------\ |
4077 \ RC5_SampleEndOf: \ <---------------------+
4078 \ ------------------------------\
4079 BIC #$30,&TA0CTL \ stop timer_A0
4080 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4081 \ ******************************\
4082 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4083 \ ******************************\
4084 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
4085 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4086 XOR IP,X \ (new XOR old) Toggle bit (13)
4087 BIT #BIT13,X \ X(13) = New_RC5_command
4088 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4090 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4091 \ ******************************\
4092 \ RC5_ComputeNewRC5word \
4093 \ ******************************\
4095 MOV &BASE,2(PSP) \ save variable BASE before use
4096 MOV TOS,0(PSP) \ save TOS before use
4097 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4098 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4099 \ ******************************\
4100 \ RC5_ComputeC6bit \
4101 \ ******************************\
4102 BIT #$4000,IP \ test /C6 bit in IP
4103 0= IF BIS #$40,TOS \ set C6 bit in S
4104 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4105 \ ******************************\
4106 \ RC5_CommandByteIsDone \ RC5_code --
4107 \ ******************************\
4109 \ ------------------------------\
4110 \ Display IR_RC5 code \
4111 \ ------------------------------\
4112 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4113 \ ------------------------------\
4114 LO2HI \ switch from assembler to FORTH
4115 ['] LCD_CLEAR IS CR \ redirects CR
4116 ['] LCD_WrC IS EMIT \ redirects EMIT
4117 $10 BASE ! \ change BASE to hexadecimal
4118 CR ." $" 2 U.R \ print IR_RC5 code
4119 ['] (CR) IS CR \ restore CR
4120 ['] (EMIT) IS EMIT \ restore EMIT
4121 HI2LO \ switch from FORTH to assembler
4122 \ ------------------------------\
4123 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4124 \ ------------------------------\
4125 MOV @PSP+,&BASE \ restore variable BASE
4126 RETI \ CPU is ON, GIE is OFF
4131 \ ------------------------------\
4132 \ TB0CTL = %0000 0010 1001 0100\$3C0
4133 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4134 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4135 \ -- \ID input divider \ 10 = /4
4136 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4137 \ - \TBCLR TimerB Clear
4140 \ --------------------------------\\
4141 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4142 \ -- \CM Capture Mode
4147 \ --- \OUTMOD \ 011 = set/reset
4153 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4155 \ ------------------------------\
4156 \ set TimerB to make 50kHz PWM \
4157 \ ------------------------------\
4158 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4159 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4160 \ ------------------------------\
4161 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4162 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4163 \ ------------------------------\
4164 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4165 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
4166 \ ------------------------------\
4167 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4168 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
4169 \ ------------------------------\
4170 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4171 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
4172 \ ------------------------------\
4173 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
4174 \ ------------------------------\
4175 \ set TimerB to generate PWM for LCD_Vo
4176 \ ------------------------------\
4177 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
4178 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
4179 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4180 \ ------------------------------\
4181 BIS.B #LCDVo,&LCDVo_DIR \
4182 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
4183 \ ------------------------------\
4184 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4185 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4186 \ ------------------------------\
4187 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4188 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4189 \ ------------------------------\
4190 \ WDT interval init part \
4191 \ ------------------------------\
4192 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
4193 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
4194 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
4195 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
4196 \ ------------------------------\
4198 \ ------------------------------\
4199 BIS.B #RC5,&IR_IE \ enable RC5_Int
4200 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4201 \ ------------------------------\
4202 \ init interrupt vectors
4203 \ ------------------------------\
4204 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
4205 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4206 \ ------------------------------\
4207 \ define LPM mode for ACCEPT \
4208 \ ------------------------------\
4209 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4210 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4211 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4213 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
4215 \ ------------------------------\
4217 \ ------------------------------\
4218 $03E8 20_US \ 1- wait 20 ms
4219 $03 TOP_LCD \ 2- send DB5=DB4=1
4220 $CD 20_US \ 3- wait 4,1 ms
4221 $03 TOP_LCD \ 4- send again DB5=DB4=1
4222 $5 20_US \ 5- wait 0,1 ms
4223 $03 TOP_LCD \ 6- send again again DB5=DB4=1
4224 $2 20_US \ wait 40 us = LCD cycle
4225 $02 TOP_LCD \ 7- send DB5=1 DB4=0
4226 $2 20_US \ wait 40 us = LCD cycle
4227 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4228 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4229 LCD_Clear \ 10- "LCD_Clear"
4230 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4231 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4232 LCD_Clear \ 10- "LCD_Clear"
4233 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4234 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4236 ['] (CR) IS CR \ ' (CR) is CR
4237 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
4239 ." RC5toLCD is running. Type STOP to quit"
4240 \ NOECHO \ uncomment to run this app without terminal connexion
4241 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
4242 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
4246 : STOP \ stops multitasking, must to be used before downloading app
4247 ['] (WARM) IS WARM \ remove START app from FORTH init process
4248 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
4256 CODE MAX \ n1 n2 -- n3 signed maximum
4257 CMP @PSP,TOS \ n2-n1
4258 S< ?GOTO FW1 \ n2<n1
4264 CODE MIN \ n1 n2 -- n3 signed minimum
4265 CMP @PSP,TOS \ n2-n1
4266 S< ?GOTO BW1 \ n2<n1
4272 : U.R \ u n -- display u unsigned in n width (n >= 2)
4274 R> OVER - 0 MAX SPACES TYPE
4278 CODE 20_US \ n -- n * 20 us
4279 BEGIN \ 3 cycles loop + 6~
4280 \ MOV #5,W \ 3 MCLK = 1 MHz
4281 \ MOV #23,W \ 3 MCLK = 4 MHz
4282 MOV #51,W \ 3 MCLK = 8 MHz
4283 \ MOV #104,W \ 3 MCLK = 16 MHz
4284 \ MOV #158,W \ 3 MCLK = 24 MHz
4285 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
4295 CODE TOP_LCD \ LCD Sample
4296 \ \ if write : %xxxxWWWW --
4297 \ \ if read : -- %0000RRRR
4298 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4299 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4300 0= IF \ write LCD bits pattern
4302 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4303 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4306 THEN \ read LCD bits pattern
4309 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4310 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4316 CODE LCD_W \ byte -- write byte to LCD
4318 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4319 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4320 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4321 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4322 COLON \ high level word starts here
4323 TOP_LCD 2 20_US \ write high nibble first
4328 CODE LCD_WrC \ char -- Write Char
4329 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4334 CODE LCD_WrF \ func -- Write Fonction
4335 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4341 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
4346 $02 LCD_WrF 100 20_us
4350 \ : LCD_Entry_set $04 OR LCD_WrF ;
4352 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
4354 \ : LCD_Display_Shift $10 OR LCD_WrF ;
4356 \ : LCD_Fn_Set $20 OR LCD_WrF ;
4358 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
4360 \ : LCD_Goto $80 OR LCD_WrF ;
4362 \ CODE LCD_R \ -- byte read byte from LCD
4363 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4364 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4365 \ COLON \ starts a FORTH word
4366 \ TOP_LCD 2 20_us \ -- %0000HHHH
4367 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4368 \ HI2LO \ switch from FORTH to assembler
4369 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4370 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4371 \ MOV @RSP+,IP \ restore IP saved by COLON
4376 \ CODE LCD_RdS \ -- status Read Status
4377 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4382 \ CODE LCD_RdC \ -- char Read Char
4383 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4388 \ -------------+------+------+------+------++---+---+---+---+---------+
4389 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
4390 \ -------------+------+------+------+------++---+---+---+---+---------+
4391 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
4392 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
4393 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
4394 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
4395 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
4396 \ -------------+------+------+------+------++---+---+---+---+---------+
4399 \ ******************************\
4400 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4401 \ ******************************\
4402 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
4403 \ ------------------------------\
4404 \ define LPM mode for ACCEPT \
4405 \ ------------------------------\
4406 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4407 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4408 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4409 BIT.B #SW2,&SW2_IN \ test switch S2
4410 0= IF \ case of switch S2 pressed
4411 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4413 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4416 BIT.B #SW1,&SW1_IN \ test switch S1 input
4417 0= IF \ case of Switch S1 pressed
4418 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4420 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4424 RETI \ CPU is ON, GIE is OFF
4429 \ ------------------------------\
4430 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4431 \ ******************************\
4432 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4433 \ ******************************\
4434 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4435 \ \ SMclock = 8|16|24 MHz
4436 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4437 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4438 \ \ SR(9)=new Toggle bit memory (ADD on)
4439 \ ------------------------------\
4440 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4441 \ ------------------------------\
4442 \ define LPM mode for ACCEPT \
4443 \ ------------------------------\
4444 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4445 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4446 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4447 \ ------------------------------\
4448 \ RC5_FirstStartBitHalfCycle: \
4449 \ ------------------------------\
4450 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4451 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4452 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4453 MOV #1778,X \ RC5_Period in us
4454 MOV #14,W \ count of loop
4456 \ ------------------------------\
4457 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4458 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4459 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4460 \ RC5_Compute_3/4_Period: \ |
4461 RRUM #1,X \ X=1/2 cycle |
4465 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4466 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4468 \ ------------------------------\
4469 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4470 \ ------------------------------\
4471 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4472 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4473 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4474 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4475 SUB #1,W \ decrement count loop
4476 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4477 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4478 0<> WHILE \ ----> out of loop ----+
4479 \ RC5_compute_7/4_Time_out: \ |
4480 ADD X,Y \ | out of bound = 7/4 period
4481 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4483 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4484 0>= IF \ | if cycle time out of bound
4485 BIC #$30,&TA0CTL \ | stop timer_A0
4486 RETI \ | then quit to do nothing
4488 \ ------------------------------\ |
4489 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4491 MOV &TA0R,X \ | | get new RC5_period value
4492 REPEAT \ ----> loop back --+ |
4493 \ ------------------------------\ |
4494 \ RC5_SampleEndOf: \ <---------------------+
4495 \ ------------------------------\
4496 BIC #$30,&TA0CTL \ stop timer_A0
4497 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4498 \ ******************************\
4499 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4500 \ ******************************\
4501 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
4502 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4503 XOR IP,X \ (new XOR old) Toggle bit (13)
4504 BIT #BIT13,X \ X(13) = New_RC5_command
4505 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4507 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4508 \ ******************************\
4509 \ RC5_ComputeNewRC5word \
4510 \ ******************************\
4512 MOV &BASE,2(PSP) \ save variable BASE before use
4513 MOV TOS,0(PSP) \ save TOS before use
4514 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4515 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4516 \ ******************************\
4517 \ RC5_ComputeC6bit \
4518 \ ******************************\
4519 BIT #$4000,IP \ test /C6 bit in IP
4520 0= IF BIS #$40,TOS \ set C6 bit in S
4521 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4522 \ ******************************\
4523 \ RC5_CommandByteIsDone \ RC5_code --
4524 \ ******************************\
4526 \ ------------------------------\
4527 \ Display IR_RC5 code \
4528 \ ------------------------------\
4529 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4530 \ ------------------------------\
4531 LO2HI \ switch from assembler to FORTH
4532 ['] LCD_CLEAR IS CR \ redirects CR
4533 ['] LCD_WrC IS EMIT \ redirects EMIT
4534 $10 BASE ! \ change BASE to hexadecimal
4535 CR ." $" 2 U.R \ print IR_RC5 code
4536 ['] (CR) IS CR \ restore CR
4537 ['] (EMIT) IS EMIT \ restore EMIT
4538 HI2LO \ switch from FORTH to assembler
4539 \ ------------------------------\
4540 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4541 \ ------------------------------\
4542 MOV @PSP+,&BASE \ restore variable BASE
4543 RETI \ CPU is ON, GIE is OFF
4548 \ ------------------------------\
4549 \ TB0CTL = %0000 0010 1001 0100\$3C0
4550 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4551 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4552 \ -- \ID input divider \ 10 = /4
4553 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4554 \ - \TBCLR TimerB Clear
4557 \ --------------------------------\\
4558 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4559 \ -- \CM Capture Mode
4564 \ --- \OUTMOD \ 011 = set/reset
4570 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4572 \ ------------------------------\
4573 \ set TimerB to make 50kHz PWM \
4574 \ ------------------------------\
4575 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4576 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4577 \ ------------------------------\
4578 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4579 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4580 \ ------------------------------\
4581 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4582 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
4583 \ ------------------------------\
4584 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4585 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
4586 \ ------------------------------\
4587 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4588 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
4589 \ ------------------------------\
4590 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
4591 \ ------------------------------\
4592 \ set TimerB to generate PWM for LCD_Vo
4593 \ ------------------------------\
4594 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
4595 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
4596 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4597 \ ------------------------------\
4598 BIS.B #LCDVo,&LCDVo_DIR \
4599 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
4600 \ ------------------------------\
4601 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4602 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4603 \ ------------------------------\
4604 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4605 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4606 \ ------------------------------\
4607 \ WDT interval init part \
4608 \ ------------------------------\
4609 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
4610 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
4611 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
4612 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
4613 \ ------------------------------\
4615 \ ------------------------------\
4616 BIS.B #RC5,&IR_IE \ enable RC5_Int
4617 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4618 \ ------------------------------\
4619 \ init interrupt vectors
4620 \ ------------------------------\
4621 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
4622 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4623 \ ------------------------------\
4624 \ define LPM mode for ACCEPT \
4625 \ ------------------------------\
4626 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4627 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4628 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4630 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
4632 \ ------------------------------\
4634 \ ------------------------------\
4635 $03E8 20_US \ 1- wait 20 ms
4636 $03 TOP_LCD \ 2- send DB5=DB4=1
4637 $CD 20_US \ 3- wait 4,1 ms
4638 $03 TOP_LCD \ 4- send again DB5=DB4=1
4639 $5 20_US \ 5- wait 0,1 ms
4640 $03 TOP_LCD \ 6- send again again DB5=DB4=1
4641 $2 20_US \ wait 40 us = LCD cycle
4642 $02 TOP_LCD \ 7- send DB5=1 DB4=0
4643 $2 20_US \ wait 40 us = LCD cycle
4644 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4645 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4646 LCD_Clear \ 10- "LCD_Clear"
4647 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4648 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4649 LCD_Clear \ 10- "LCD_Clear"
4650 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4651 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4653 ['] (CR) IS CR \ ' (CR) is CR
4654 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
4656 ." RC5toLCD is running. Type STOP to quit"
4657 \ NOECHO \ uncomment to run this app without terminal connexion
4658 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
4659 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
4663 : STOP \ stops multitasking, must to be used before downloading app
4664 ['] (WARM) IS WARM \ remove START app from FORTH init process
4665 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
4673 CODE MAX \ n1 n2 -- n3 signed maximum
4674 CMP @PSP,TOS \ n2-n1
4675 S< ?GOTO FW1 \ n2<n1
4681 CODE MIN \ n1 n2 -- n3 signed minimum
4682 CMP @PSP,TOS \ n2-n1
4683 S< ?GOTO BW1 \ n2<n1
4689 : U.R \ u n -- display u unsigned in n width (n >= 2)
4691 R> OVER - 0 MAX SPACES TYPE
4695 CODE 20_US \ n -- n * 20 us
4696 BEGIN \ 3 cycles loop + 6~
4697 \ MOV #5,W \ 3 MCLK = 1 MHz
4698 \ MOV #23,W \ 3 MCLK = 4 MHz
4699 MOV #51,W \ 3 MCLK = 8 MHz
4700 \ MOV #104,W \ 3 MCLK = 16 MHz
4701 \ MOV #158,W \ 3 MCLK = 24 MHz
4702 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
4712 CODE TOP_LCD \ LCD Sample
4713 \ \ if write : %xxxxWWWW --
4714 \ \ if read : -- %0000RRRR
4715 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4716 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4717 0= IF \ write LCD bits pattern
4719 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4720 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4723 THEN \ read LCD bits pattern
4726 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4727 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4733 CODE LCD_W \ byte -- write byte to LCD
4735 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4736 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4737 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4738 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4739 COLON \ high level word starts here
4740 TOP_LCD 2 20_US \ write high nibble first
4745 CODE LCD_WrC \ char -- Write Char
4746 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4751 CODE LCD_WrF \ func -- Write Fonction
4752 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4758 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
4763 $02 LCD_WrF 100 20_us
4767 \ : LCD_Entry_set $04 OR LCD_WrF ;
4769 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
4771 \ : LCD_Display_Shift $10 OR LCD_WrF ;
4773 \ : LCD_Fn_Set $20 OR LCD_WrF ;
4775 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
4777 \ : LCD_Goto $80 OR LCD_WrF ;
4779 \ CODE LCD_R \ -- byte read byte from LCD
4780 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4781 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4782 \ COLON \ starts a FORTH word
4783 \ TOP_LCD 2 20_us \ -- %0000HHHH
4784 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4785 \ HI2LO \ switch from FORTH to assembler
4786 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4787 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4788 \ MOV @RSP+,IP \ restore IP saved by COLON
4793 \ CODE LCD_RdS \ -- status Read Status
4794 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4799 \ CODE LCD_RdC \ -- char Read Char
4800 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4805 \ -------------+------+------+------+------++---+---+---+---+---------+
4806 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
4807 \ -------------+------+------+------+------++---+---+---+---+---------+
4808 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
4809 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
4810 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
4811 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
4812 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
4813 \ -------------+------+------+------+------++---+---+---+---+---------+
4816 \ ******************************\
4817 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4818 \ ******************************\
4819 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
4820 \ ------------------------------\
4821 \ define LPM mode for ACCEPT \
4822 \ ------------------------------\
4823 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4824 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4825 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4826 BIT.B #SW2,&SW2_IN \ test switch S2
4827 0= IF \ case of switch S2 pressed
4828 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4830 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4833 BIT.B #SW1,&SW1_IN \ test switch S1 input
4834 0= IF \ case of Switch S1 pressed
4835 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4837 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4841 RETI \ CPU is ON, GIE is OFF
4846 \ ------------------------------\
4847 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4848 \ ******************************\
4849 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4850 \ ******************************\
4851 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4852 \ \ SMclock = 8|16|24 MHz
4853 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4854 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4855 \ \ SR(9)=new Toggle bit memory (ADD on)
4856 \ ------------------------------\
4857 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4858 \ ------------------------------\
4859 \ define LPM mode for ACCEPT \
4860 \ ------------------------------\
4861 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4862 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4863 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4864 \ ------------------------------\
4865 \ RC5_FirstStartBitHalfCycle: \
4866 \ ------------------------------\
4867 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4868 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4869 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4870 MOV #1778,X \ RC5_Period in us
4871 MOV #14,W \ count of loop
4873 \ ------------------------------\
4874 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4875 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4876 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4877 \ RC5_Compute_3/4_Period: \ |
4878 RRUM #1,X \ X=1/2 cycle |
4882 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4883 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4885 \ ------------------------------\
4886 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4887 \ ------------------------------\
4888 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4889 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4890 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4891 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4892 SUB #1,W \ decrement count loop
4893 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4894 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4895 0<> WHILE \ ----> out of loop ----+
4896 \ RC5_compute_7/4_Time_out: \ |
4897 ADD X,Y \ | out of bound = 7/4 period
4898 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4900 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4901 0>= IF \ | if cycle time out of bound
4902 BIC #$30,&TA0CTL \ | stop timer_A0
4903 RETI \ | then quit to do nothing
4905 \ ------------------------------\ |
4906 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4908 MOV &TA0R,X \ | | get new RC5_period value
4909 REPEAT \ ----> loop back --+ |
4910 \ ------------------------------\ |
4911 \ RC5_SampleEndOf: \ <---------------------+
4912 \ ------------------------------\
4913 BIC #$30,&TA0CTL \ stop timer_A0
4914 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4915 \ ******************************\
4916 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4917 \ ******************************\
4918 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
4919 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4920 XOR IP,X \ (new XOR old) Toggle bit (13)
4921 BIT #BIT13,X \ X(13) = New_RC5_command
4922 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4924 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4925 \ ******************************\
4926 \ RC5_ComputeNewRC5word \
4927 \ ******************************\
4929 MOV &BASE,2(PSP) \ save variable BASE before use
4930 MOV TOS,0(PSP) \ save TOS before use
4931 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4932 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4933 \ ******************************\
4934 \ RC5_ComputeC6bit \
4935 \ ******************************\
4936 BIT #$4000,IP \ test /C6 bit in IP
4937 0= IF BIS #$40,TOS \ set C6 bit in S
4938 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4939 \ ******************************\
4940 \ RC5_CommandByteIsDone \ RC5_code --
4941 \ ******************************\
4943 \ ------------------------------\
4944 \ Display IR_RC5 code \
4945 \ ------------------------------\
4946 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4947 \ ------------------------------\
4948 LO2HI \ switch from assembler to FORTH
4949 ['] LCD_CLEAR IS CR \ redirects CR
4950 ['] LCD_WrC IS EMIT \ redirects EMIT
4951 $10 BASE ! \ change BASE to hexadecimal
4952 CR ." $" 2 U.R \ print IR_RC5 code
4953 ['] (CR) IS CR \ restore CR
4954 ['] (EMIT) IS EMIT \ restore EMIT
4955 HI2LO \ switch from FORTH to assembler
4956 \ ------------------------------\
4957 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4958 \ ------------------------------\
4959 MOV @PSP+,&BASE \ restore variable BASE
4960 RETI \ CPU is ON, GIE is OFF
4965 \ ------------------------------\
4966 \ TB0CTL = %0000 0010 1001 0100\$3C0
4967 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4968 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4969 \ -- \ID input divider \ 10 = /4
4970 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4971 \ - \TBCLR TimerB Clear
4974 \ --------------------------------\\
4975 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4976 \ -- \CM Capture Mode
4981 \ --- \OUTMOD \ 011 = set/reset
4987 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4989 \ ------------------------------\
4990 \ set TimerB to make 50kHz PWM \
4991 \ ------------------------------\
4992 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4993 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4994 \ ------------------------------\
4995 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4996 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4997 \ ------------------------------\
4998 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4999 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
5000 \ ------------------------------\
5001 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5002 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
5003 \ ------------------------------\
5004 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5005 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
5006 \ ------------------------------\
5007 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
5008 \ ------------------------------\
5009 \ set TimerB to generate PWM for LCD_Vo
5010 \ ------------------------------\
5011 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
5012 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
5013 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5014 \ ------------------------------\
5015 BIS.B #LCDVo,&LCDVo_DIR \
5016 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
5017 \ ------------------------------\
5018 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5019 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5020 \ ------------------------------\
5021 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5022 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5023 \ ------------------------------\
5024 \ WDT interval init part \
5025 \ ------------------------------\
5026 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
5027 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
5028 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
5029 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
5030 \ ------------------------------\
5032 \ ------------------------------\
5033 BIS.B #RC5,&IR_IE \ enable RC5_Int
5034 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5035 \ ------------------------------\
5036 \ init interrupt vectors
5037 \ ------------------------------\
5038 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
5039 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5040 \ ------------------------------\
5041 \ define LPM mode for ACCEPT \
5042 \ ------------------------------\
5043 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5044 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5045 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5047 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
5049 \ ------------------------------\
5051 \ ------------------------------\
5052 $03E8 20_US \ 1- wait 20 ms
5053 $03 TOP_LCD \ 2- send DB5=DB4=1
5054 $CD 20_US \ 3- wait 4,1 ms
5055 $03 TOP_LCD \ 4- send again DB5=DB4=1
5056 $5 20_US \ 5- wait 0,1 ms
5057 $03 TOP_LCD \ 6- send again again DB5=DB4=1
5058 $2 20_US \ wait 40 us = LCD cycle
5059 $02 TOP_LCD \ 7- send DB5=1 DB4=0
5060 $2 20_US \ wait 40 us = LCD cycle
5061 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5062 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5063 LCD_Clear \ 10- "LCD_Clear"
5064 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5065 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5066 LCD_Clear \ 10- "LCD_Clear"
5067 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5068 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5070 ['] (CR) IS CR \ ' (CR) is CR
5071 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
5073 ." RC5toLCD is running. Type STOP to quit"
5074 \ NOECHO \ uncomment to run this app without terminal connexion
5075 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
5076 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
5080 : STOP \ stops multitasking, must to be used before downloading app
5081 ['] (WARM) IS WARM \ remove START app from FORTH init process
5082 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
5090 CODE MAX \ n1 n2 -- n3 signed maximum
5091 CMP @PSP,TOS \ n2-n1
5092 S< ?GOTO FW1 \ n2<n1
5098 CODE MIN \ n1 n2 -- n3 signed minimum
5099 CMP @PSP,TOS \ n2-n1
5100 S< ?GOTO BW1 \ n2<n1
5106 : U.R \ u n -- display u unsigned in n width (n >= 2)
5108 R> OVER - 0 MAX SPACES TYPE
5112 CODE 20_US \ n -- n * 20 us
5113 BEGIN \ 3 cycles loop + 6~
5114 \ MOV #5,W \ 3 MCLK = 1 MHz
5115 \ MOV #23,W \ 3 MCLK = 4 MHz
5116 MOV #51,W \ 3 MCLK = 8 MHz
5117 \ MOV #104,W \ 3 MCLK = 16 MHz
5118 \ MOV #158,W \ 3 MCLK = 24 MHz
5119 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
5129 CODE TOP_LCD \ LCD Sample
5130 \ \ if write : %xxxxWWWW --
5131 \ \ if read : -- %0000RRRR
5132 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5133 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5134 0= IF \ write LCD bits pattern
5136 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5137 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5140 THEN \ read LCD bits pattern
5143 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5144 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5150 CODE LCD_W \ byte -- write byte to LCD
5152 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5153 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5154 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5155 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5156 COLON \ high level word starts here
5157 TOP_LCD 2 20_US \ write high nibble first
5162 CODE LCD_WrC \ char -- Write Char
5163 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5168 CODE LCD_WrF \ func -- Write Fonction
5169 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5175 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
5180 $02 LCD_WrF 100 20_us
5184 \ : LCD_Entry_set $04 OR LCD_WrF ;
5186 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
5188 \ : LCD_Display_Shift $10 OR LCD_WrF ;
5190 \ : LCD_Fn_Set $20 OR LCD_WrF ;
5192 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
5194 \ : LCD_Goto $80 OR LCD_WrF ;
5196 \ CODE LCD_R \ -- byte read byte from LCD
5197 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5198 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5199 \ COLON \ starts a FORTH word
5200 \ TOP_LCD 2 20_us \ -- %0000HHHH
5201 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5202 \ HI2LO \ switch from FORTH to assembler
5203 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5204 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5205 \ MOV @RSP+,IP \ restore IP saved by COLON
5210 \ CODE LCD_RdS \ -- status Read Status
5211 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5216 \ CODE LCD_RdC \ -- char Read Char
5217 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5222 \ -------------+------+------+------+------++---+---+---+---+---------+
5223 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
5224 \ -------------+------+------+------+------++---+---+---+---+---------+
5225 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
5226 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
5227 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
5228 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
5229 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
5230 \ -------------+------+------+------+------++---+---+---+---+---------+
5233 \ ******************************\
5234 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5235 \ ******************************\
5236 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
5237 \ ------------------------------\
5238 \ define LPM mode for ACCEPT \
5239 \ ------------------------------\
5240 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5241 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5242 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5243 BIT.B #SW2,&SW2_IN \ test switch S2
5244 0= IF \ case of switch S2 pressed
5245 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
5247 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
5250 BIT.B #SW1,&SW1_IN \ test switch S1 input
5251 0= IF \ case of Switch S1 pressed
5252 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
5254 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
5258 RETI \ CPU is ON, GIE is OFF
5263 \ ------------------------------\
5264 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5265 \ ******************************\
5266 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5267 \ ******************************\
5268 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5269 \ \ SMclock = 8|16|24 MHz
5270 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
5271 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
5272 \ \ SR(9)=new Toggle bit memory (ADD on)
5273 \ ------------------------------\
5274 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
5275 \ ------------------------------\
5276 \ define LPM mode for ACCEPT \
5277 \ ------------------------------\
5278 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5279 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5280 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5281 \ ------------------------------\
5282 \ RC5_FirstStartBitHalfCycle: \
5283 \ ------------------------------\
5284 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
5285 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
5286 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
5287 MOV #1778,X \ RC5_Period in us
5288 MOV #14,W \ count of loop
5290 \ ------------------------------\
5291 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
5292 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
5293 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
5294 \ RC5_Compute_3/4_Period: \ |
5295 RRUM #1,X \ X=1/2 cycle |
5299 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
5300 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
5302 \ ------------------------------\
5303 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
5304 \ ------------------------------\
5305 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5306 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
5307 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5308 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5309 SUB #1,W \ decrement count loop
5310 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
5311 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5312 0<> WHILE \ ----> out of loop ----+
5313 \ RC5_compute_7/4_Time_out: \ |
5314 ADD X,Y \ | out of bound = 7/4 period
5315 \ RC5_WaitHalfCycleP1.2_IFG: \ |
5317 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
5318 0>= IF \ | if cycle time out of bound
5319 BIC #$30,&TA0CTL \ | stop timer_A0
5320 RETI \ | then quit to do nothing
5322 \ ------------------------------\ |
5323 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
5325 MOV &TA0R,X \ | | get new RC5_period value
5326 REPEAT \ ----> loop back --+ |
5327 \ ------------------------------\ |
5328 \ RC5_SampleEndOf: \ <---------------------+
5329 \ ------------------------------\
5330 BIC #$30,&TA0CTL \ stop timer_A0
5331 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
5332 \ ******************************\
5333 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5334 \ ******************************\
5335 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
5336 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
5337 XOR IP,X \ (new XOR old) Toggle bit (13)
5338 BIT #BIT13,X \ X(13) = New_RC5_command
5339 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
5341 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
5342 \ ******************************\
5343 \ RC5_ComputeNewRC5word \
5344 \ ******************************\
5346 MOV &BASE,2(PSP) \ save variable BASE before use
5347 MOV TOS,0(PSP) \ save TOS before use
5348 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
5349 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
5350 \ ******************************\
5351 \ RC5_ComputeC6bit \
5352 \ ******************************\
5353 BIT #$4000,IP \ test /C6 bit in IP
5354 0= IF BIS #$40,TOS \ set C6 bit in S
5355 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
5356 \ ******************************\
5357 \ RC5_CommandByteIsDone \ RC5_code --
5358 \ ******************************\
5360 \ ------------------------------\
5361 \ Display IR_RC5 code \
5362 \ ------------------------------\
5363 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
5364 \ ------------------------------\
5365 LO2HI \ switch from assembler to FORTH
5366 ['] LCD_CLEAR IS CR \ redirects CR
5367 ['] LCD_WrC IS EMIT \ redirects EMIT
5368 $10 BASE ! \ change BASE to hexadecimal
5369 CR ." $" 2 U.R \ print IR_RC5 code
5370 ['] (CR) IS CR \ restore CR
5371 ['] (EMIT) IS EMIT \ restore EMIT
5372 HI2LO \ switch from FORTH to assembler
5373 \ ------------------------------\
5374 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
5375 \ ------------------------------\
5376 MOV @PSP+,&BASE \ restore variable BASE
5377 RETI \ CPU is ON, GIE is OFF
5382 \ ------------------------------\
5383 \ TB0CTL = %0000 0010 1001 0100\$3C0
5384 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5385 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5386 \ -- \ID input divider \ 10 = /4
5387 \ -- \MC Mode Control \ 01 = up to TB0CCR0
5388 \ - \TBCLR TimerB Clear
5391 \ --------------------------------\\
5392 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5393 \ -- \CM Capture Mode
5398 \ --- \OUTMOD \ 011 = set/reset
5404 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
5406 \ ------------------------------\
5407 \ set TimerB to make 50kHz PWM \
5408 \ ------------------------------\
5409 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5410 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
5411 \ ------------------------------\
5412 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5413 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
5414 \ ------------------------------\
5415 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5416 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
5417 \ ------------------------------\
5418 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5419 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
5420 \ ------------------------------\
5421 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5422 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
5423 \ ------------------------------\
5424 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
5425 \ ------------------------------\
5426 \ set TimerB to generate PWM for LCD_Vo
5427 \ ------------------------------\
5428 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
5429 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
5430 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5431 \ ------------------------------\
5432 BIS.B #LCDVo,&LCDVo_DIR \
5433 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
5434 \ ------------------------------\
5435 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5436 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5437 \ ------------------------------\
5438 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5439 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5440 \ ------------------------------\
5441 \ WDT interval init part \
5442 \ ------------------------------\
5443 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
5444 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
5445 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
5446 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
5447 \ ------------------------------\
5449 \ ------------------------------\
5450 BIS.B #RC5,&IR_IE \ enable RC5_Int
5451 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5452 \ ------------------------------\
5453 \ init interrupt vectors
5454 \ ------------------------------\
5455 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
5456 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5457 \ ------------------------------\
5458 \ define LPM mode for ACCEPT \
5459 \ ------------------------------\
5460 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5461 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5462 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5464 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
5466 \ ------------------------------\
5468 \ ------------------------------\
5469 $03E8 20_US \ 1- wait 20 ms
5470 $03 TOP_LCD \ 2- send DB5=DB4=1
5471 $CD 20_US \ 3- wait 4,1 ms
5472 $03 TOP_LCD \ 4- send again DB5=DB4=1
5473 $5 20_US \ 5- wait 0,1 ms
5474 $03 TOP_LCD \ 6- send again again DB5=DB4=1
5475 $2 20_US \ wait 40 us = LCD cycle
5476 $02 TOP_LCD \ 7- send DB5=1 DB4=0
5477 $2 20_US \ wait 40 us = LCD cycle
5478 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5479 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5480 LCD_Clear \ 10- "LCD_Clear"
5481 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5482 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5483 LCD_Clear \ 10- "LCD_Clear"
5484 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5485 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5487 ['] (CR) IS CR \ ' (CR) is CR
5488 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
5490 ." RC5toLCD is running. Type STOP to quit"
5491 \ NOECHO \ uncomment to run this app without terminal connexion
5492 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
5493 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
5497 : STOP \ stops multitasking, must to be used before downloading app
5498 ['] (WARM) IS WARM \ remove START app from FORTH init process
5499 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
5507 CODE MAX \ n1 n2 -- n3 signed maximum
5508 CMP @PSP,TOS \ n2-n1
5509 S< ?GOTO FW1 \ n2<n1
5515 CODE MIN \ n1 n2 -- n3 signed minimum
5516 CMP @PSP,TOS \ n2-n1
5517 S< ?GOTO BW1 \ n2<n1
5523 : U.R \ u n -- display u unsigned in n width (n >= 2)
5525 R> OVER - 0 MAX SPACES TYPE
5529 CODE 20_US \ n -- n * 20 us
5530 BEGIN \ 3 cycles loop + 6~
5531 \ MOV #5,W \ 3 MCLK = 1 MHz
5532 \ MOV #23,W \ 3 MCLK = 4 MHz
5533 MOV #51,W \ 3 MCLK = 8 MHz
5534 \ MOV #104,W \ 3 MCLK = 16 MHz
5535 \ MOV #158,W \ 3 MCLK = 24 MHz
5536 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
5546 CODE TOP_LCD \ LCD Sample
5547 \ \ if write : %xxxxWWWW --
5548 \ \ if read : -- %0000RRRR
5549 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5550 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5551 0= IF \ write LCD bits pattern
5553 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5554 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5557 THEN \ read LCD bits pattern
5560 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5561 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5567 CODE LCD_W \ byte -- write byte to LCD
5569 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5570 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5571 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5572 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5573 COLON \ high level word starts here
5574 TOP_LCD 2 20_US \ write high nibble first
5579 CODE LCD_WrC \ char -- Write Char
5580 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5585 CODE LCD_WrF \ func -- Write Fonction
5586 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5592 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
5597 $02 LCD_WrF 100 20_us
5601 \ : LCD_Entry_set $04 OR LCD_WrF ;
5603 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
5605 \ : LCD_Display_Shift $10 OR LCD_WrF ;
5607 \ : LCD_Fn_Set $20 OR LCD_WrF ;
5609 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
5611 \ : LCD_Goto $80 OR LCD_WrF ;
5613 \ CODE LCD_R \ -- byte read byte from LCD
5614 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5615 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5616 \ COLON \ starts a FORTH word
5617 \ TOP_LCD 2 20_us \ -- %0000HHHH
5618 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
5619 \ HI2LO \ switch from FORTH to assembler
5620 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
5621 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
5622 \ MOV @RSP+,IP \ restore IP saved by COLON
5627 \ CODE LCD_RdS \ -- status Read Status
5628 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5633 \ CODE LCD_RdC \ -- char Read Char
5634 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5639 \ -------------+------+------+------+------++---+---+---+---+---------+
5640 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
5641 \ -------------+------+------+------+------++---+---+---+---+---------+
5642 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
5643 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
5644 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
5645 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
5646 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
5647 \ -------------+------+------+------+------++---+---+---+---+---------+
5650 \ ******************************\
5651 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5652 \ ******************************\
5653 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
5654 \ ------------------------------\
5655 \ define LPM mode for ACCEPT \
5656 \ ------------------------------\
5657 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5658 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5659 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5660 BIT.B #SW2,&SW2_IN \ test switch S2
5661 0= IF \ case of switch S2 pressed
5662 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
5664 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
5667 BIT.B #SW1,&SW1_IN \ test switch S1 input
5668 0= IF \ case of Switch S1 pressed
5669 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
5671 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
5675 RETI \ CPU is ON, GIE is OFF
5680 \ ------------------------------\
5681 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5682 \ ******************************\
5683 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5684 \ ******************************\
5685 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5686 \ \ SMclock = 8|16|24 MHz
5687 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
5688 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
5689 \ \ SR(9)=new Toggle bit memory (ADD on)
5690 \ ------------------------------\
5691 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
5692 \ ------------------------------\
5693 \ define LPM mode for ACCEPT \
5694 \ ------------------------------\
5695 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5696 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5697 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5698 \ ------------------------------\
5699 \ RC5_FirstStartBitHalfCycle: \
5700 \ ------------------------------\
5701 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
5702 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
5703 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
5704 MOV #1778,X \ RC5_Period in us
5705 MOV #14,W \ count of loop
5707 \ ------------------------------\
5708 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
5709 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
5710 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
5711 \ RC5_Compute_3/4_Period: \ |
5712 RRUM #1,X \ X=1/2 cycle |
5716 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
5717 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
5719 \ ------------------------------\
5720 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
5721 \ ------------------------------\
5722 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5723 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
5724 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5725 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5726 SUB #1,W \ decrement count loop
5727 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
5728 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5729 0<> WHILE \ ----> out of loop ----+
5730 \ RC5_compute_7/4_Time_out: \ |
5731 ADD X,Y \ | out of bound = 7/4 period
5732 \ RC5_WaitHalfCycleP1.2_IFG: \ |
5734 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
5735 0>= IF \ | if cycle time out of bound
5736 BIC #$30,&TA0CTL \ | stop timer_A0
5737 RETI \ | then quit to do nothing
5739 \ ------------------------------\ |
5740 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
5742 MOV &TA0R,X \ | | get new RC5_period value
5743 REPEAT \ ----> loop back --+ |
5744 \ ------------------------------\ |
5745 \ RC5_SampleEndOf: \ <---------------------+
5746 \ ------------------------------\
5747 BIC #$30,&TA0CTL \ stop timer_A0
5748 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
5749 \ ******************************\
5750 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5751 \ ******************************\
5752 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
5753 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
5754 XOR IP,X \ (new XOR old) Toggle bit (13)
5755 BIT #BIT13,X \ X(13) = New_RC5_command
5756 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
5758 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
5759 \ ******************************\
5760 \ RC5_ComputeNewRC5word \
5761 \ ******************************\
5763 MOV &BASE,2(PSP) \ save variable BASE before use
5764 MOV TOS,0(PSP) \ save TOS before use
5765 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
5766 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
5767 \ ******************************\
5768 \ RC5_ComputeC6bit \
5769 \ ******************************\
5770 BIT #$4000,IP \ test /C6 bit in IP
5771 0= IF BIS #$40,TOS \ set C6 bit in S
5772 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
5773 \ ******************************\
5774 \ RC5_CommandByteIsDone \ RC5_code --
5775 \ ******************************\
5777 \ ------------------------------\
5778 \ Display IR_RC5 code \
5779 \ ------------------------------\
5780 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
5781 \ ------------------------------\
5782 LO2HI \ switch from assembler to FORTH
5783 ['] LCD_CLEAR IS CR \ redirects CR
5784 ['] LCD_WrC IS EMIT \ redirects EMIT
5785 $10 BASE ! \ change BASE to hexadecimal
5786 CR ." $" 2 U.R \ print IR_RC5 code
5787 ['] (CR) IS CR \ restore CR
5788 ['] (EMIT) IS EMIT \ restore EMIT
5789 HI2LO \ switch from FORTH to assembler
5790 \ ------------------------------\
5791 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
5792 \ ------------------------------\
5793 MOV @PSP+,&BASE \ restore variable BASE
5794 RETI \ CPU is ON, GIE is OFF
5799 \ ------------------------------\
5800 \ TB0CTL = %0000 0010 1001 0100\$3C0
5801 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5802 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5803 \ -- \ID input divider \ 10 = /4
5804 \ -- \MC Mode Control \ 01 = up to TB0CCR0
5805 \ - \TBCLR TimerB Clear
5808 \ --------------------------------\\
5809 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5810 \ -- \CM Capture Mode
5815 \ --- \OUTMOD \ 011 = set/reset
5821 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
5823 \ ------------------------------\
5824 \ set TimerB to make 50kHz PWM \
5825 \ ------------------------------\
5826 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5827 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
5828 \ ------------------------------\
5829 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
5830 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
5831 \ ------------------------------\
5832 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5833 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
5834 \ ------------------------------\
5835 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5836 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
5837 \ ------------------------------\
5838 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
5839 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
5840 \ ------------------------------\
5841 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
5842 \ ------------------------------\
5843 \ set TimerB to generate PWM for LCD_Vo
5844 \ ------------------------------\
5845 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
5846 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
5847 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5848 \ ------------------------------\
5849 BIS.B #LCDVo,&LCDVo_DIR \
5850 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
5851 \ ------------------------------\
5852 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5853 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5854 \ ------------------------------\
5855 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5856 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5857 \ ------------------------------\
5858 \ WDT interval init part \
5859 \ ------------------------------\
5860 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
5861 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
5862 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
5863 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
5864 \ ------------------------------\
5866 \ ------------------------------\
5867 BIS.B #RC5,&IR_IE \ enable RC5_Int
5868 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5869 \ ------------------------------\
5870 \ init interrupt vectors
5871 \ ------------------------------\
5872 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
5873 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5874 \ ------------------------------\
5875 \ define LPM mode for ACCEPT \
5876 \ ------------------------------\
5877 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5878 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5879 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5881 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
5883 \ ------------------------------\
5885 \ ------------------------------\
5886 $03E8 20_US \ 1- wait 20 ms
5887 $03 TOP_LCD \ 2- send DB5=DB4=1
5888 $CD 20_US \ 3- wait 4,1 ms
5889 $03 TOP_LCD \ 4- send again DB5=DB4=1
5890 $5 20_US \ 5- wait 0,1 ms
5891 $03 TOP_LCD \ 6- send again again DB5=DB4=1
5892 $2 20_US \ wait 40 us = LCD cycle
5893 $02 TOP_LCD \ 7- send DB5=1 DB4=0
5894 $2 20_US \ wait 40 us = LCD cycle
5895 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5896 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5897 LCD_Clear \ 10- "LCD_Clear"
5898 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5899 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5900 LCD_Clear \ 10- "LCD_Clear"
5901 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5902 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5904 ['] (CR) IS CR \ ' (CR) is CR
5905 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
5907 ." RC5toLCD is running. Type STOP to quit"
5908 \ NOECHO \ uncomment to run this app without terminal connexion
5909 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
5910 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
5914 : STOP \ stops multitasking, must to be used before downloading app
5915 ['] (WARM) IS WARM \ remove START app from FORTH init process
5916 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
5924 CODE MAX \ n1 n2 -- n3 signed maximum
5925 CMP @PSP,TOS \ n2-n1
5926 S< ?GOTO FW1 \ n2<n1
5932 CODE MIN \ n1 n2 -- n3 signed minimum
5933 CMP @PSP,TOS \ n2-n1
5934 S< ?GOTO BW1 \ n2<n1
5940 : U.R \ u n -- display u unsigned in n width (n >= 2)
5942 R> OVER - 0 MAX SPACES TYPE
5946 CODE 20_US \ n -- n * 20 us
5947 BEGIN \ 3 cycles loop + 6~
5948 \ MOV #5,W \ 3 MCLK = 1 MHz
5949 \ MOV #23,W \ 3 MCLK = 4 MHz
5950 MOV #51,W \ 3 MCLK = 8 MHz
5951 \ MOV #104,W \ 3 MCLK = 16 MHz
5952 \ MOV #158,W \ 3 MCLK = 24 MHz
5953 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
5963 CODE TOP_LCD \ LCD Sample
5964 \ \ if write : %xxxxWWWW --
5965 \ \ if read : -- %0000RRRR
5966 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5967 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5968 0= IF \ write LCD bits pattern
5970 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5971 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5974 THEN \ read LCD bits pattern
5977 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5978 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5984 CODE LCD_W \ byte -- write byte to LCD
5986 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
5987 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
5988 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5989 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5990 COLON \ high level word starts here
5991 TOP_LCD 2 20_US \ write high nibble first
5996 CODE LCD_WrC \ char -- Write Char
5997 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6002 CODE LCD_WrF \ func -- Write Fonction
6003 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6009 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
6014 $02 LCD_WrF 100 20_us
6018 \ : LCD_Entry_set $04 OR LCD_WrF ;
6020 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
6022 \ : LCD_Display_Shift $10 OR LCD_WrF ;
6024 \ : LCD_Fn_Set $20 OR LCD_WrF ;
6026 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
6028 \ : LCD_Goto $80 OR LCD_WrF ;
6030 \ CODE LCD_R \ -- byte read byte from LCD
6031 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6032 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6033 \ COLON \ starts a FORTH word
6034 \ TOP_LCD 2 20_us \ -- %0000HHHH
6035 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6036 \ HI2LO \ switch from FORTH to assembler
6037 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6038 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6039 \ MOV @RSP+,IP \ restore IP saved by COLON
6044 \ CODE LCD_RdS \ -- status Read Status
6045 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6050 \ CODE LCD_RdC \ -- char Read Char
6051 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6056 \ -------------+------+------+------+------++---+---+---+---+---------+
6057 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
6058 \ -------------+------+------+------+------++---+---+---+---+---------+
6059 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
6060 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
6061 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
6062 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
6063 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
6064 \ -------------+------+------+------+------++---+---+---+---+---------+
6067 \ ******************************\
6068 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6069 \ ******************************\
6070 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
6071 \ ------------------------------\
6072 \ define LPM mode for ACCEPT \
6073 \ ------------------------------\
6074 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6075 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6076 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6077 BIT.B #SW2,&SW2_IN \ test switch S2
6078 0= IF \ case of switch S2 pressed
6079 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
6081 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
6084 BIT.B #SW1,&SW1_IN \ test switch S1 input
6085 0= IF \ case of Switch S1 pressed
6086 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
6088 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
6092 RETI \ CPU is ON, GIE is OFF
6097 \ ------------------------------\
6098 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6099 \ ******************************\
6100 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6101 \ ******************************\
6102 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6103 \ \ SMclock = 8|16|24 MHz
6104 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
6105 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
6106 \ \ SR(9)=new Toggle bit memory (ADD on)
6107 \ ------------------------------\
6108 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
6109 \ ------------------------------\
6110 \ define LPM mode for ACCEPT \
6111 \ ------------------------------\
6112 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6113 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6114 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6115 \ ------------------------------\
6116 \ RC5_FirstStartBitHalfCycle: \
6117 \ ------------------------------\
6118 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
6119 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
6120 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
6121 MOV #1778,X \ RC5_Period in us
6122 MOV #14,W \ count of loop
6124 \ ------------------------------\
6125 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
6126 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
6127 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
6128 \ RC5_Compute_3/4_Period: \ |
6129 RRUM #1,X \ X=1/2 cycle |
6133 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
6134 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
6136 \ ------------------------------\
6137 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
6138 \ ------------------------------\
6139 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6140 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
6141 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6142 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6143 SUB #1,W \ decrement count loop
6144 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
6145 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6146 0<> WHILE \ ----> out of loop ----+
6147 \ RC5_compute_7/4_Time_out: \ |
6148 ADD X,Y \ | out of bound = 7/4 period
6149 \ RC5_WaitHalfCycleP1.2_IFG: \ |
6151 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
6152 0>= IF \ | if cycle time out of bound
6153 BIC #$30,&TA0CTL \ | stop timer_A0
6154 RETI \ | then quit to do nothing
6156 \ ------------------------------\ |
6157 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
6159 MOV &TA0R,X \ | | get new RC5_period value
6160 REPEAT \ ----> loop back --+ |
6161 \ ------------------------------\ |
6162 \ RC5_SampleEndOf: \ <---------------------+
6163 \ ------------------------------\
6164 BIC #$30,&TA0CTL \ stop timer_A0
6165 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
6166 \ ******************************\
6167 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6168 \ ******************************\
6169 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
6170 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
6171 XOR IP,X \ (new XOR old) Toggle bit (13)
6172 BIT #BIT13,X \ X(13) = New_RC5_command
6173 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
6175 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
6176 \ ******************************\
6177 \ RC5_ComputeNewRC5word \
6178 \ ******************************\
6180 MOV &BASE,2(PSP) \ save variable BASE before use
6181 MOV TOS,0(PSP) \ save TOS before use
6182 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
6183 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
6184 \ ******************************\
6185 \ RC5_ComputeC6bit \
6186 \ ******************************\
6187 BIT #$4000,IP \ test /C6 bit in IP
6188 0= IF BIS #$40,TOS \ set C6 bit in S
6189 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
6190 \ ******************************\
6191 \ RC5_CommandByteIsDone \ RC5_code --
6192 \ ******************************\
6194 \ ------------------------------\
6195 \ Display IR_RC5 code \
6196 \ ------------------------------\
6197 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
6198 \ ------------------------------\
6199 LO2HI \ switch from assembler to FORTH
6200 ['] LCD_CLEAR IS CR \ redirects CR
6201 ['] LCD_WrC IS EMIT \ redirects EMIT
6202 $10 BASE ! \ change BASE to hexadecimal
6203 CR ." $" 2 U.R \ print IR_RC5 code
6204 ['] (CR) IS CR \ restore CR
6205 ['] (EMIT) IS EMIT \ restore EMIT
6206 HI2LO \ switch from FORTH to assembler
6207 \ ------------------------------\
6208 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
6209 \ ------------------------------\
6210 MOV @PSP+,&BASE \ restore variable BASE
6211 RETI \ CPU is ON, GIE is OFF
6216 \ ------------------------------\
6217 \ TB0CTL = %0000 0010 1001 0100\$3C0
6218 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6219 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6220 \ -- \ID input divider \ 10 = /4
6221 \ -- \MC Mode Control \ 01 = up to TB0CCR0
6222 \ - \TBCLR TimerB Clear
6225 \ --------------------------------\\
6226 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6227 \ -- \CM Capture Mode
6232 \ --- \OUTMOD \ 011 = set/reset
6238 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
6240 \ ------------------------------\
6241 \ set TimerB to make 50kHz PWM \
6242 \ ------------------------------\
6243 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6244 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
6245 \ ------------------------------\
6246 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6247 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
6248 \ ------------------------------\
6249 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6250 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
6251 \ ------------------------------\
6252 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6253 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
6254 \ ------------------------------\
6255 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6256 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
6257 \ ------------------------------\
6258 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
6259 \ ------------------------------\
6260 \ set TimerB to generate PWM for LCD_Vo
6261 \ ------------------------------\
6262 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
6263 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
6264 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6265 \ ------------------------------\
6266 BIS.B #LCDVo,&LCDVo_DIR \
6267 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
6268 \ ------------------------------\
6269 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6270 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6271 \ ------------------------------\
6272 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6273 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6274 \ ------------------------------\
6275 \ WDT interval init part \
6276 \ ------------------------------\
6277 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
6278 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
6279 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
6280 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
6281 \ ------------------------------\
6283 \ ------------------------------\
6284 BIS.B #RC5,&IR_IE \ enable RC5_Int
6285 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6286 \ ------------------------------\
6287 \ init interrupt vectors
6288 \ ------------------------------\
6289 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
6290 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6291 \ ------------------------------\
6292 \ define LPM mode for ACCEPT \
6293 \ ------------------------------\
6294 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6295 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6296 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6298 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
6300 \ ------------------------------\
6302 \ ------------------------------\
6303 $03E8 20_US \ 1- wait 20 ms
6304 $03 TOP_LCD \ 2- send DB5=DB4=1
6305 $CD 20_US \ 3- wait 4,1 ms
6306 $03 TOP_LCD \ 4- send again DB5=DB4=1
6307 $5 20_US \ 5- wait 0,1 ms
6308 $03 TOP_LCD \ 6- send again again DB5=DB4=1
6309 $2 20_US \ wait 40 us = LCD cycle
6310 $02 TOP_LCD \ 7- send DB5=1 DB4=0
6311 $2 20_US \ wait 40 us = LCD cycle
6312 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6313 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6314 LCD_Clear \ 10- "LCD_Clear"
6315 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6316 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6317 LCD_Clear \ 10- "LCD_Clear"
6318 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6319 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6321 ['] (CR) IS CR \ ' (CR) is CR
6322 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
6324 ." RC5toLCD is running. Type STOP to quit"
6325 \ NOECHO \ uncomment to run this app without terminal connexion
6326 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
6327 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
6331 : STOP \ stops multitasking, must to be used before downloading app
6332 ['] (WARM) IS WARM \ remove START app from FORTH init process
6333 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
6341 CODE MAX \ n1 n2 -- n3 signed maximum
6342 CMP @PSP,TOS \ n2-n1
6343 S< ?GOTO FW1 \ n2<n1
6349 CODE MIN \ n1 n2 -- n3 signed minimum
6350 CMP @PSP,TOS \ n2-n1
6351 S< ?GOTO BW1 \ n2<n1
6357 : U.R \ u n -- display u unsigned in n width (n >= 2)
6359 R> OVER - 0 MAX SPACES TYPE
6363 CODE 20_US \ n -- n * 20 us
6364 BEGIN \ 3 cycles loop + 6~
6365 \ MOV #5,W \ 3 MCLK = 1 MHz
6366 \ MOV #23,W \ 3 MCLK = 4 MHz
6367 MOV #51,W \ 3 MCLK = 8 MHz
6368 \ MOV #104,W \ 3 MCLK = 16 MHz
6369 \ MOV #158,W \ 3 MCLK = 24 MHz
6370 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
6380 CODE TOP_LCD \ LCD Sample
6381 \ \ if write : %xxxxWWWW --
6382 \ \ if read : -- %0000RRRR
6383 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6384 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6385 0= IF \ write LCD bits pattern
6387 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6388 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6391 THEN \ read LCD bits pattern
6394 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6395 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6401 CODE LCD_W \ byte -- write byte to LCD
6403 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
6404 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
6405 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6406 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6407 COLON \ high level word starts here
6408 TOP_LCD 2 20_US \ write high nibble first
6413 CODE LCD_WrC \ char -- Write Char
6414 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6419 CODE LCD_WrF \ func -- Write Fonction
6420 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6426 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
6431 $02 LCD_WrF 100 20_us
6435 \ : LCD_Entry_set $04 OR LCD_WrF ;
6437 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
6439 \ : LCD_Display_Shift $10 OR LCD_WrF ;
6441 \ : LCD_Fn_Set $20 OR LCD_WrF ;
6443 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
6445 \ : LCD_Goto $80 OR LCD_WrF ;
6447 \ CODE LCD_R \ -- byte read byte from LCD
6448 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6449 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6450 \ COLON \ starts a FORTH word
6451 \ TOP_LCD 2 20_us \ -- %0000HHHH
6452 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6453 \ HI2LO \ switch from FORTH to assembler
6454 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6455 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6456 \ MOV @RSP+,IP \ restore IP saved by COLON
6461 \ CODE LCD_RdS \ -- status Read Status
6462 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6467 \ CODE LCD_RdC \ -- char Read Char
6468 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6473 \ -------------+------+------+------+------++---+---+---+---+---------+
6474 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
6475 \ -------------+------+------+------+------++---+---+---+---+---------+
6476 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
6477 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
6478 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
6479 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
6480 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
6481 \ -------------+------+------+------+------++---+---+---+---+---------+
6484 \ ******************************\
6485 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6486 \ ******************************\
6487 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
6488 \ ------------------------------\
6489 \ define LPM mode for ACCEPT \
6490 \ ------------------------------\
6491 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6492 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6493 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6494 BIT.B #SW2,&SW2_IN \ test switch S2
6495 0= IF \ case of switch S2 pressed
6496 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
6498 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
6501 BIT.B #SW1,&SW1_IN \ test switch S1 input
6502 0= IF \ case of Switch S1 pressed
6503 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
6505 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
6509 RETI \ CPU is ON, GIE is OFF
6514 \ ------------------------------\
6515 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6516 \ ******************************\
6517 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6518 \ ******************************\
6519 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6520 \ \ SMclock = 8|16|24 MHz
6521 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
6522 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
6523 \ \ SR(9)=new Toggle bit memory (ADD on)
6524 \ ------------------------------\
6525 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
6526 \ ------------------------------\
6527 \ define LPM mode for ACCEPT \
6528 \ ------------------------------\
6529 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6530 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6531 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6532 \ ------------------------------\
6533 \ RC5_FirstStartBitHalfCycle: \
6534 \ ------------------------------\
6535 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
6536 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
6537 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
6538 MOV #1778,X \ RC5_Period in us
6539 MOV #14,W \ count of loop
6541 \ ------------------------------\
6542 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
6543 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
6544 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
6545 \ RC5_Compute_3/4_Period: \ |
6546 RRUM #1,X \ X=1/2 cycle |
6550 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
6551 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
6553 \ ------------------------------\
6554 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
6555 \ ------------------------------\
6556 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6557 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
6558 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6559 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6560 SUB #1,W \ decrement count loop
6561 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
6562 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6563 0<> WHILE \ ----> out of loop ----+
6564 \ RC5_compute_7/4_Time_out: \ |
6565 ADD X,Y \ | out of bound = 7/4 period
6566 \ RC5_WaitHalfCycleP1.2_IFG: \ |
6568 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
6569 0>= IF \ | if cycle time out of bound
6570 BIC #$30,&TA0CTL \ | stop timer_A0
6571 RETI \ | then quit to do nothing
6573 \ ------------------------------\ |
6574 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
6576 MOV &TA0R,X \ | | get new RC5_period value
6577 REPEAT \ ----> loop back --+ |
6578 \ ------------------------------\ |
6579 \ RC5_SampleEndOf: \ <---------------------+
6580 \ ------------------------------\
6581 BIC #$30,&TA0CTL \ stop timer_A0
6582 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
6583 \ ******************************\
6584 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6585 \ ******************************\
6586 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
6587 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
6588 XOR IP,X \ (new XOR old) Toggle bit (13)
6589 BIT #BIT13,X \ X(13) = New_RC5_command
6590 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
6592 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
6593 \ ******************************\
6594 \ RC5_ComputeNewRC5word \
6595 \ ******************************\
6597 MOV &BASE,2(PSP) \ save variable BASE before use
6598 MOV TOS,0(PSP) \ save TOS before use
6599 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
6600 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
6601 \ ******************************\
6602 \ RC5_ComputeC6bit \
6603 \ ******************************\
6604 BIT #$4000,IP \ test /C6 bit in IP
6605 0= IF BIS #$40,TOS \ set C6 bit in S
6606 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
6607 \ ******************************\
6608 \ RC5_CommandByteIsDone \ RC5_code --
6609 \ ******************************\
6611 \ ------------------------------\
6612 \ Display IR_RC5 code \
6613 \ ------------------------------\
6614 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
6615 \ ------------------------------\
6616 LO2HI \ switch from assembler to FORTH
6617 ['] LCD_CLEAR IS CR \ redirects CR
6618 ['] LCD_WrC IS EMIT \ redirects EMIT
6619 $10 BASE ! \ change BASE to hexadecimal
6620 CR ." $" 2 U.R \ print IR_RC5 code
6621 ['] (CR) IS CR \ restore CR
6622 ['] (EMIT) IS EMIT \ restore EMIT
6623 HI2LO \ switch from FORTH to assembler
6624 \ ------------------------------\
6625 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
6626 \ ------------------------------\
6627 MOV @PSP+,&BASE \ restore variable BASE
6628 RETI \ CPU is ON, GIE is OFF
6633 \ ------------------------------\
6634 \ TB0CTL = %0000 0010 1001 0100\$3C0
6635 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6636 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6637 \ -- \ID input divider \ 10 = /4
6638 \ -- \MC Mode Control \ 01 = up to TB0CCR0
6639 \ - \TBCLR TimerB Clear
6642 \ --------------------------------\\
6643 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6644 \ -- \CM Capture Mode
6649 \ --- \OUTMOD \ 011 = set/reset
6655 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
6657 \ ------------------------------\
6658 \ set TimerB to make 50kHz PWM \
6659 \ ------------------------------\
6660 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6661 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
6662 \ ------------------------------\
6663 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
6664 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
6665 \ ------------------------------\
6666 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6667 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
6668 \ ------------------------------\
6669 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6670 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
6671 \ ------------------------------\
6672 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
6673 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
6674 \ ------------------------------\
6675 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
6676 \ ------------------------------\
6677 \ set TimerB to generate PWM for LCD_Vo
6678 \ ------------------------------\
6679 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
6680 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
6681 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6682 \ ------------------------------\
6683 BIS.B #LCDVo,&LCDVo_DIR \
6684 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
6685 \ ------------------------------\
6686 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6687 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6688 \ ------------------------------\
6689 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6690 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6691 \ ------------------------------\
6692 \ WDT interval init part \
6693 \ ------------------------------\
6694 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
6695 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
6696 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
6697 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
6698 \ ------------------------------\
6700 \ ------------------------------\
6701 BIS.B #RC5,&IR_IE \ enable RC5_Int
6702 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6703 \ ------------------------------\
6704 \ init interrupt vectors
6705 \ ------------------------------\
6706 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
6707 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6708 \ ------------------------------\
6709 \ define LPM mode for ACCEPT \
6710 \ ------------------------------\
6711 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6712 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6713 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6715 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
6717 \ ------------------------------\
6719 \ ------------------------------\
6720 $03E8 20_US \ 1- wait 20 ms
6721 $03 TOP_LCD \ 2- send DB5=DB4=1
6722 $CD 20_US \ 3- wait 4,1 ms
6723 $03 TOP_LCD \ 4- send again DB5=DB4=1
6724 $5 20_US \ 5- wait 0,1 ms
6725 $03 TOP_LCD \ 6- send again again DB5=DB4=1
6726 $2 20_US \ wait 40 us = LCD cycle
6727 $02 TOP_LCD \ 7- send DB5=1 DB4=0
6728 $2 20_US \ wait 40 us = LCD cycle
6729 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6730 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6731 LCD_Clear \ 10- "LCD_Clear"
6732 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6733 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6734 LCD_Clear \ 10- "LCD_Clear"
6735 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6736 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6738 ['] (CR) IS CR \ ' (CR) is CR
6739 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
6741 ." RC5toLCD is running. Type STOP to quit"
6742 \ NOECHO \ uncomment to run this app without terminal connexion
6743 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
6744 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
6748 : STOP \ stops multitasking, must to be used before downloading app
6749 ['] (WARM) IS WARM \ remove START app from FORTH init process
6750 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
6758 CODE MAX \ n1 n2 -- n3 signed maximum
6759 CMP @PSP,TOS \ n2-n1
6760 S< ?GOTO FW1 \ n2<n1
6766 CODE MIN \ n1 n2 -- n3 signed minimum
6767 CMP @PSP,TOS \ n2-n1
6768 S< ?GOTO BW1 \ n2<n1
6774 : U.R \ u n -- display u unsigned in n width (n >= 2)
6776 R> OVER - 0 MAX SPACES TYPE
6780 CODE 20_US \ n -- n * 20 us
6781 BEGIN \ 3 cycles loop + 6~
6782 \ MOV #5,W \ 3 MCLK = 1 MHz
6783 \ MOV #23,W \ 3 MCLK = 4 MHz
6784 MOV #51,W \ 3 MCLK = 8 MHz
6785 \ MOV #104,W \ 3 MCLK = 16 MHz
6786 \ MOV #158,W \ 3 MCLK = 24 MHz
6787 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
6797 CODE TOP_LCD \ LCD Sample
6798 \ \ if write : %xxxxWWWW --
6799 \ \ if read : -- %0000RRRR
6800 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6801 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6802 0= IF \ write LCD bits pattern
6804 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6805 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6808 THEN \ read LCD bits pattern
6811 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6812 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6818 CODE LCD_W \ byte -- write byte to LCD
6820 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
6821 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
6822 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6823 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6824 COLON \ high level word starts here
6825 TOP_LCD 2 20_US \ write high nibble first
6830 CODE LCD_WrC \ char -- Write Char
6831 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6836 CODE LCD_WrF \ func -- Write Fonction
6837 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6843 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
6848 $02 LCD_WrF 100 20_us
6852 \ : LCD_Entry_set $04 OR LCD_WrF ;
6854 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
6856 \ : LCD_Display_Shift $10 OR LCD_WrF ;
6858 \ : LCD_Fn_Set $20 OR LCD_WrF ;
6860 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
6862 \ : LCD_Goto $80 OR LCD_WrF ;
6864 \ CODE LCD_R \ -- byte read byte from LCD
6865 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6866 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6867 \ COLON \ starts a FORTH word
6868 \ TOP_LCD 2 20_us \ -- %0000HHHH
6869 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
6870 \ HI2LO \ switch from FORTH to assembler
6871 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
6872 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
6873 \ MOV @RSP+,IP \ restore IP saved by COLON
6878 \ CODE LCD_RdS \ -- status Read Status
6879 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6884 \ CODE LCD_RdC \ -- char Read Char
6885 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6890 \ -------------+------+------+------+------++---+---+---+---+---------+
6891 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
6892 \ -------------+------+------+------+------++---+---+---+---+---------+
6893 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
6894 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
6895 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
6896 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
6897 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
6898 \ -------------+------+------+------+------++---+---+---+---+---------+
6901 \ ******************************\
6902 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6903 \ ******************************\
6904 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
6905 \ ------------------------------\
6906 \ define LPM mode for ACCEPT \
6907 \ ------------------------------\
6908 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6909 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6910 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6911 BIT.B #SW2,&SW2_IN \ test switch S2
6912 0= IF \ case of switch S2 pressed
6913 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
6915 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
6918 BIT.B #SW1,&SW1_IN \ test switch S1 input
6919 0= IF \ case of Switch S1 pressed
6920 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
6922 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
6926 RETI \ CPU is ON, GIE is OFF
6931 \ ------------------------------\
6932 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6933 \ ******************************\
6934 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6935 \ ******************************\
6936 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6937 \ \ SMclock = 8|16|24 MHz
6938 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
6939 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
6940 \ \ SR(9)=new Toggle bit memory (ADD on)
6941 \ ------------------------------\
6942 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
6943 \ ------------------------------\
6944 \ define LPM mode for ACCEPT \
6945 \ ------------------------------\
6946 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6947 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6948 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6949 \ ------------------------------\
6950 \ RC5_FirstStartBitHalfCycle: \
6951 \ ------------------------------\
6952 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
6953 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
6954 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
6955 MOV #1778,X \ RC5_Period in us
6956 MOV #14,W \ count of loop
6958 \ ------------------------------\
6959 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
6960 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
6961 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
6962 \ RC5_Compute_3/4_Period: \ |
6963 RRUM #1,X \ X=1/2 cycle |
6967 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
6968 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
6970 \ ------------------------------\
6971 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
6972 \ ------------------------------\
6973 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6974 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
6975 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6976 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6977 SUB #1,W \ decrement count loop
6978 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
6979 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6980 0<> WHILE \ ----> out of loop ----+
6981 \ RC5_compute_7/4_Time_out: \ |
6982 ADD X,Y \ | out of bound = 7/4 period
6983 \ RC5_WaitHalfCycleP1.2_IFG: \ |
6985 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
6986 0>= IF \ | if cycle time out of bound
6987 BIC #$30,&TA0CTL \ | stop timer_A0
6988 RETI \ | then quit to do nothing
6990 \ ------------------------------\ |
6991 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
6993 MOV &TA0R,X \ | | get new RC5_period value
6994 REPEAT \ ----> loop back --+ |
6995 \ ------------------------------\ |
6996 \ RC5_SampleEndOf: \ <---------------------+
6997 \ ------------------------------\
6998 BIC #$30,&TA0CTL \ stop timer_A0
6999 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
7000 \ ******************************\
7001 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7002 \ ******************************\
7003 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
7004 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
7005 XOR IP,X \ (new XOR old) Toggle bit (13)
7006 BIT #BIT13,X \ X(13) = New_RC5_command
7007 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
7009 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
7010 \ ******************************\
7011 \ RC5_ComputeNewRC5word \
7012 \ ******************************\
7014 MOV &BASE,2(PSP) \ save variable BASE before use
7015 MOV TOS,0(PSP) \ save TOS before use
7016 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
7017 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
7018 \ ******************************\
7019 \ RC5_ComputeC6bit \
7020 \ ******************************\
7021 BIT #$4000,IP \ test /C6 bit in IP
7022 0= IF BIS #$40,TOS \ set C6 bit in S
7023 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
7024 \ ******************************\
7025 \ RC5_CommandByteIsDone \ RC5_code --
7026 \ ******************************\
7028 \ ------------------------------\
7029 \ Display IR_RC5 code \
7030 \ ------------------------------\
7031 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
7032 \ ------------------------------\
7033 LO2HI \ switch from assembler to FORTH
7034 ['] LCD_CLEAR IS CR \ redirects CR
7035 ['] LCD_WrC IS EMIT \ redirects EMIT
7036 $10 BASE ! \ change BASE to hexadecimal
7037 CR ." $" 2 U.R \ print IR_RC5 code
7038 ['] (CR) IS CR \ restore CR
7039 ['] (EMIT) IS EMIT \ restore EMIT
7040 HI2LO \ switch from FORTH to assembler
7041 \ ------------------------------\
7042 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
7043 \ ------------------------------\
7044 MOV @PSP+,&BASE \ restore variable BASE
7045 RETI \ CPU is ON, GIE is OFF
7050 \ ------------------------------\
7051 \ TB0CTL = %0000 0010 1001 0100\$3C0
7052 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7053 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7054 \ -- \ID input divider \ 10 = /4
7055 \ -- \MC Mode Control \ 01 = up to TB0CCR0
7056 \ - \TBCLR TimerB Clear
7059 \ --------------------------------\\
7060 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7061 \ -- \CM Capture Mode
7066 \ --- \OUTMOD \ 011 = set/reset
7072 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
7074 \ ------------------------------\
7075 \ set TimerB to make 50kHz PWM \
7076 \ ------------------------------\
7077 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7078 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
7079 \ ------------------------------\
7080 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7081 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
7082 \ ------------------------------\
7083 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7084 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
7085 \ ------------------------------\
7086 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7087 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
7088 \ ------------------------------\
7089 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7090 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
7091 \ ------------------------------\
7092 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
7093 \ ------------------------------\
7094 \ set TimerB to generate PWM for LCD_Vo
7095 \ ------------------------------\
7096 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
7097 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
7098 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7099 \ ------------------------------\
7100 BIS.B #LCDVo,&LCDVo_DIR \
7101 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
7102 \ ------------------------------\
7103 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7104 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7105 \ ------------------------------\
7106 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7107 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7108 \ ------------------------------\
7109 \ WDT interval init part \
7110 \ ------------------------------\
7111 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
7112 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
7113 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
7114 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
7115 \ ------------------------------\
7117 \ ------------------------------\
7118 BIS.B #RC5,&IR_IE \ enable RC5_Int
7119 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7120 \ ------------------------------\
7121 \ init interrupt vectors
7122 \ ------------------------------\
7123 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
7124 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7125 \ ------------------------------\
7126 \ define LPM mode for ACCEPT \
7127 \ ------------------------------\
7128 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7129 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7130 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7132 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
7134 \ ------------------------------\
7136 \ ------------------------------\
7137 $03E8 20_US \ 1- wait 20 ms
7138 $03 TOP_LCD \ 2- send DB5=DB4=1
7139 $CD 20_US \ 3- wait 4,1 ms
7140 $03 TOP_LCD \ 4- send again DB5=DB4=1
7141 $5 20_US \ 5- wait 0,1 ms
7142 $03 TOP_LCD \ 6- send again again DB5=DB4=1
7143 $2 20_US \ wait 40 us = LCD cycle
7144 $02 TOP_LCD \ 7- send DB5=1 DB4=0
7145 $2 20_US \ wait 40 us = LCD cycle
7146 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7147 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7148 LCD_Clear \ 10- "LCD_Clear"
7149 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7150 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7151 LCD_Clear \ 10- "LCD_Clear"
7152 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7153 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7155 ['] (CR) IS CR \ ' (CR) is CR
7156 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
7158 ." RC5toLCD is running. Type STOP to quit"
7159 \ NOECHO \ uncomment to run this app without terminal connexion
7160 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
7161 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
7165 : STOP \ stops multitasking, must to be used before downloading app
7166 ['] (WARM) IS WARM \ remove START app from FORTH init process
7167 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
7175 CODE MAX \ n1 n2 -- n3 signed maximum
7176 CMP @PSP,TOS \ n2-n1
7177 S< ?GOTO FW1 \ n2<n1
7183 CODE MIN \ n1 n2 -- n3 signed minimum
7184 CMP @PSP,TOS \ n2-n1
7185 S< ?GOTO BW1 \ n2<n1
7191 : U.R \ u n -- display u unsigned in n width (n >= 2)
7193 R> OVER - 0 MAX SPACES TYPE
7197 CODE 20_US \ n -- n * 20 us
7198 BEGIN \ 3 cycles loop + 6~
7199 \ MOV #5,W \ 3 MCLK = 1 MHz
7200 \ MOV #23,W \ 3 MCLK = 4 MHz
7201 MOV #51,W \ 3 MCLK = 8 MHz
7202 \ MOV #104,W \ 3 MCLK = 16 MHz
7203 \ MOV #158,W \ 3 MCLK = 24 MHz
7204 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
7214 CODE TOP_LCD \ LCD Sample
7215 \ \ if write : %xxxxWWWW --
7216 \ \ if read : -- %0000RRRR
7217 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7218 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7219 0= IF \ write LCD bits pattern
7221 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7222 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7225 THEN \ read LCD bits pattern
7228 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7229 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7235 CODE LCD_W \ byte -- write byte to LCD
7237 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7238 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7239 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7240 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7241 COLON \ high level word starts here
7242 TOP_LCD 2 20_US \ write high nibble first
7247 CODE LCD_WrC \ char -- Write Char
7248 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7253 CODE LCD_WrF \ func -- Write Fonction
7254 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7260 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
7265 $02 LCD_WrF 100 20_us
7269 \ : LCD_Entry_set $04 OR LCD_WrF ;
7271 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
7273 \ : LCD_Display_Shift $10 OR LCD_WrF ;
7275 \ : LCD_Fn_Set $20 OR LCD_WrF ;
7277 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
7279 \ : LCD_Goto $80 OR LCD_WrF ;
7281 \ CODE LCD_R \ -- byte read byte from LCD
7282 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7283 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7284 \ COLON \ starts a FORTH word
7285 \ TOP_LCD 2 20_us \ -- %0000HHHH
7286 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7287 \ HI2LO \ switch from FORTH to assembler
7288 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7289 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7290 \ MOV @RSP+,IP \ restore IP saved by COLON
7295 \ CODE LCD_RdS \ -- status Read Status
7296 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7301 \ CODE LCD_RdC \ -- char Read Char
7302 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7307 \ -------------+------+------+------+------++---+---+---+---+---------+
7308 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
7309 \ -------------+------+------+------+------++---+---+---+---+---------+
7310 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
7311 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
7312 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
7313 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
7314 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
7315 \ -------------+------+------+------+------++---+---+---+---+---------+
7318 \ ******************************\
7319 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7320 \ ******************************\
7321 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
7322 \ ------------------------------\
7323 \ define LPM mode for ACCEPT \
7324 \ ------------------------------\
7325 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7326 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7327 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7328 BIT.B #SW2,&SW2_IN \ test switch S2
7329 0= IF \ case of switch S2 pressed
7330 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
7332 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
7335 BIT.B #SW1,&SW1_IN \ test switch S1 input
7336 0= IF \ case of Switch S1 pressed
7337 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
7339 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
7343 RETI \ CPU is ON, GIE is OFF
7348 \ ------------------------------\
7349 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7350 \ ******************************\
7351 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7352 \ ******************************\
7353 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7354 \ \ SMclock = 8|16|24 MHz
7355 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
7356 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
7357 \ \ SR(9)=new Toggle bit memory (ADD on)
7358 \ ------------------------------\
7359 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
7360 \ ------------------------------\
7361 \ define LPM mode for ACCEPT \
7362 \ ------------------------------\
7363 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7364 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7365 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7366 \ ------------------------------\
7367 \ RC5_FirstStartBitHalfCycle: \
7368 \ ------------------------------\
7369 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
7370 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
7371 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
7372 MOV #1778,X \ RC5_Period in us
7373 MOV #14,W \ count of loop
7375 \ ------------------------------\
7376 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
7377 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
7378 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
7379 \ RC5_Compute_3/4_Period: \ |
7380 RRUM #1,X \ X=1/2 cycle |
7384 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
7385 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
7387 \ ------------------------------\
7388 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
7389 \ ------------------------------\
7390 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7391 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
7392 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7393 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7394 SUB #1,W \ decrement count loop
7395 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
7396 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7397 0<> WHILE \ ----> out of loop ----+
7398 \ RC5_compute_7/4_Time_out: \ |
7399 ADD X,Y \ | out of bound = 7/4 period
7400 \ RC5_WaitHalfCycleP1.2_IFG: \ |
7402 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
7403 0>= IF \ | if cycle time out of bound
7404 BIC #$30,&TA0CTL \ | stop timer_A0
7405 RETI \ | then quit to do nothing
7407 \ ------------------------------\ |
7408 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
7410 MOV &TA0R,X \ | | get new RC5_period value
7411 REPEAT \ ----> loop back --+ |
7412 \ ------------------------------\ |
7413 \ RC5_SampleEndOf: \ <---------------------+
7414 \ ------------------------------\
7415 BIC #$30,&TA0CTL \ stop timer_A0
7416 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
7417 \ ******************************\
7418 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7419 \ ******************************\
7420 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
7421 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
7422 XOR IP,X \ (new XOR old) Toggle bit (13)
7423 BIT #BIT13,X \ X(13) = New_RC5_command
7424 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
7426 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
7427 \ ******************************\
7428 \ RC5_ComputeNewRC5word \
7429 \ ******************************\
7431 MOV &BASE,2(PSP) \ save variable BASE before use
7432 MOV TOS,0(PSP) \ save TOS before use
7433 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
7434 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
7435 \ ******************************\
7436 \ RC5_ComputeC6bit \
7437 \ ******************************\
7438 BIT #$4000,IP \ test /C6 bit in IP
7439 0= IF BIS #$40,TOS \ set C6 bit in S
7440 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
7441 \ ******************************\
7442 \ RC5_CommandByteIsDone \ RC5_code --
7443 \ ******************************\
7445 \ ------------------------------\
7446 \ Display IR_RC5 code \
7447 \ ------------------------------\
7448 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
7449 \ ------------------------------\
7450 LO2HI \ switch from assembler to FORTH
7451 ['] LCD_CLEAR IS CR \ redirects CR
7452 ['] LCD_WrC IS EMIT \ redirects EMIT
7453 $10 BASE ! \ change BASE to hexadecimal
7454 CR ." $" 2 U.R \ print IR_RC5 code
7455 ['] (CR) IS CR \ restore CR
7456 ['] (EMIT) IS EMIT \ restore EMIT
7457 HI2LO \ switch from FORTH to assembler
7458 \ ------------------------------\
7459 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
7460 \ ------------------------------\
7461 MOV @PSP+,&BASE \ restore variable BASE
7462 RETI \ CPU is ON, GIE is OFF
7467 \ ------------------------------\
7468 \ TB0CTL = %0000 0010 1001 0100\$3C0
7469 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7470 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7471 \ -- \ID input divider \ 10 = /4
7472 \ -- \MC Mode Control \ 01 = up to TB0CCR0
7473 \ - \TBCLR TimerB Clear
7476 \ --------------------------------\\
7477 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7478 \ -- \CM Capture Mode
7483 \ --- \OUTMOD \ 011 = set/reset
7489 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
7491 \ ------------------------------\
7492 \ set TimerB to make 50kHz PWM \
7493 \ ------------------------------\
7494 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7495 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
7496 \ ------------------------------\
7497 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7498 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
7499 \ ------------------------------\
7500 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7501 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
7502 \ ------------------------------\
7503 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7504 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
7505 \ ------------------------------\
7506 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7507 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
7508 \ ------------------------------\
7509 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
7510 \ ------------------------------\
7511 \ set TimerB to generate PWM for LCD_Vo
7512 \ ------------------------------\
7513 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
7514 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
7515 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7516 \ ------------------------------\
7517 BIS.B #LCDVo,&LCDVo_DIR \
7518 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
7519 \ ------------------------------\
7520 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7521 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7522 \ ------------------------------\
7523 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7524 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7525 \ ------------------------------\
7526 \ WDT interval init part \
7527 \ ------------------------------\
7528 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
7529 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
7530 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
7531 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
7532 \ ------------------------------\
7534 \ ------------------------------\
7535 BIS.B #RC5,&IR_IE \ enable RC5_Int
7536 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7537 \ ------------------------------\
7538 \ init interrupt vectors
7539 \ ------------------------------\
7540 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
7541 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7542 \ ------------------------------\
7543 \ define LPM mode for ACCEPT \
7544 \ ------------------------------\
7545 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7546 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7547 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7549 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
7551 \ ------------------------------\
7553 \ ------------------------------\
7554 $03E8 20_US \ 1- wait 20 ms
7555 $03 TOP_LCD \ 2- send DB5=DB4=1
7556 $CD 20_US \ 3- wait 4,1 ms
7557 $03 TOP_LCD \ 4- send again DB5=DB4=1
7558 $5 20_US \ 5- wait 0,1 ms
7559 $03 TOP_LCD \ 6- send again again DB5=DB4=1
7560 $2 20_US \ wait 40 us = LCD cycle
7561 $02 TOP_LCD \ 7- send DB5=1 DB4=0
7562 $2 20_US \ wait 40 us = LCD cycle
7563 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7564 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7565 LCD_Clear \ 10- "LCD_Clear"
7566 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7567 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7568 LCD_Clear \ 10- "LCD_Clear"
7569 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7570 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7572 ['] (CR) IS CR \ ' (CR) is CR
7573 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
7575 ." RC5toLCD is running. Type STOP to quit"
7576 \ NOECHO \ uncomment to run this app without terminal connexion
7577 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
7578 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
7582 : STOP \ stops multitasking, must to be used before downloading app
7583 ['] (WARM) IS WARM \ remove START app from FORTH init process
7584 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
7592 CODE MAX \ n1 n2 -- n3 signed maximum
7593 CMP @PSP,TOS \ n2-n1
7594 S< ?GOTO FW1 \ n2<n1
7600 CODE MIN \ n1 n2 -- n3 signed minimum
7601 CMP @PSP,TOS \ n2-n1
7602 S< ?GOTO BW1 \ n2<n1
7608 : U.R \ u n -- display u unsigned in n width (n >= 2)
7610 R> OVER - 0 MAX SPACES TYPE
7614 CODE 20_US \ n -- n * 20 us
7615 BEGIN \ 3 cycles loop + 6~
7616 \ MOV #5,W \ 3 MCLK = 1 MHz
7617 \ MOV #23,W \ 3 MCLK = 4 MHz
7618 MOV #51,W \ 3 MCLK = 8 MHz
7619 \ MOV #104,W \ 3 MCLK = 16 MHz
7620 \ MOV #158,W \ 3 MCLK = 24 MHz
7621 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
7631 CODE TOP_LCD \ LCD Sample
7632 \ \ if write : %xxxxWWWW --
7633 \ \ if read : -- %0000RRRR
7634 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7635 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7636 0= IF \ write LCD bits pattern
7638 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7639 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7642 THEN \ read LCD bits pattern
7645 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7646 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7652 CODE LCD_W \ byte -- write byte to LCD
7654 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
7655 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
7656 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7657 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7658 COLON \ high level word starts here
7659 TOP_LCD 2 20_US \ write high nibble first
7664 CODE LCD_WrC \ char -- Write Char
7665 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7670 CODE LCD_WrF \ func -- Write Fonction
7671 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7677 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
7682 $02 LCD_WrF 100 20_us
7686 \ : LCD_Entry_set $04 OR LCD_WrF ;
7688 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
7690 \ : LCD_Display_Shift $10 OR LCD_WrF ;
7692 \ : LCD_Fn_Set $20 OR LCD_WrF ;
7694 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
7696 \ : LCD_Goto $80 OR LCD_WrF ;
7698 \ CODE LCD_R \ -- byte read byte from LCD
7699 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7700 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7701 \ COLON \ starts a FORTH word
7702 \ TOP_LCD 2 20_us \ -- %0000HHHH
7703 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
7704 \ HI2LO \ switch from FORTH to assembler
7705 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
7706 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
7707 \ MOV @RSP+,IP \ restore IP saved by COLON
7712 \ CODE LCD_RdS \ -- status Read Status
7713 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7718 \ CODE LCD_RdC \ -- char Read Char
7719 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7724 \ -------------+------+------+------+------++---+---+---+---+---------+
7725 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
7726 \ -------------+------+------+------+------++---+---+---+---+---------+
7727 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
7728 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
7729 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
7730 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
7731 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
7732 \ -------------+------+------+------+------++---+---+---+---+---------+
7735 \ ******************************\
7736 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7737 \ ******************************\
7738 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
7739 \ ------------------------------\
7740 \ define LPM mode for ACCEPT \
7741 \ ------------------------------\
7742 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7743 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7744 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7745 BIT.B #SW2,&SW2_IN \ test switch S2
7746 0= IF \ case of switch S2 pressed
7747 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
7749 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
7752 BIT.B #SW1,&SW1_IN \ test switch S1 input
7753 0= IF \ case of Switch S1 pressed
7754 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
7756 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
7760 RETI \ CPU is ON, GIE is OFF
7765 \ ------------------------------\
7766 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7767 \ ******************************\
7768 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7769 \ ******************************\
7770 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7771 \ \ SMclock = 8|16|24 MHz
7772 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
7773 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
7774 \ \ SR(9)=new Toggle bit memory (ADD on)
7775 \ ------------------------------\
7776 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
7777 \ ------------------------------\
7778 \ define LPM mode for ACCEPT \
7779 \ ------------------------------\
7780 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7781 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7782 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7783 \ ------------------------------\
7784 \ RC5_FirstStartBitHalfCycle: \
7785 \ ------------------------------\
7786 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
7787 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
7788 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
7789 MOV #1778,X \ RC5_Period in us
7790 MOV #14,W \ count of loop
7792 \ ------------------------------\
7793 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
7794 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
7795 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
7796 \ RC5_Compute_3/4_Period: \ |
7797 RRUM #1,X \ X=1/2 cycle |
7801 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
7802 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
7804 \ ------------------------------\
7805 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
7806 \ ------------------------------\
7807 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7808 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
7809 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7810 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7811 SUB #1,W \ decrement count loop
7812 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
7813 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7814 0<> WHILE \ ----> out of loop ----+
7815 \ RC5_compute_7/4_Time_out: \ |
7816 ADD X,Y \ | out of bound = 7/4 period
7817 \ RC5_WaitHalfCycleP1.2_IFG: \ |
7819 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
7820 0>= IF \ | if cycle time out of bound
7821 BIC #$30,&TA0CTL \ | stop timer_A0
7822 RETI \ | then quit to do nothing
7824 \ ------------------------------\ |
7825 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
7827 MOV &TA0R,X \ | | get new RC5_period value
7828 REPEAT \ ----> loop back --+ |
7829 \ ------------------------------\ |
7830 \ RC5_SampleEndOf: \ <---------------------+
7831 \ ------------------------------\
7832 BIC #$30,&TA0CTL \ stop timer_A0
7833 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
7834 \ ******************************\
7835 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7836 \ ******************************\
7837 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
7838 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
7839 XOR IP,X \ (new XOR old) Toggle bit (13)
7840 BIT #BIT13,X \ X(13) = New_RC5_command
7841 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
7843 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
7844 \ ******************************\
7845 \ RC5_ComputeNewRC5word \
7846 \ ******************************\
7848 MOV &BASE,2(PSP) \ save variable BASE before use
7849 MOV TOS,0(PSP) \ save TOS before use
7850 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
7851 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
7852 \ ******************************\
7853 \ RC5_ComputeC6bit \
7854 \ ******************************\
7855 BIT #$4000,IP \ test /C6 bit in IP
7856 0= IF BIS #$40,TOS \ set C6 bit in S
7857 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
7858 \ ******************************\
7859 \ RC5_CommandByteIsDone \ RC5_code --
7860 \ ******************************\
7862 \ ------------------------------\
7863 \ Display IR_RC5 code \
7864 \ ------------------------------\
7865 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
7866 \ ------------------------------\
7867 LO2HI \ switch from assembler to FORTH
7868 ['] LCD_CLEAR IS CR \ redirects CR
7869 ['] LCD_WrC IS EMIT \ redirects EMIT
7870 $10 BASE ! \ change BASE to hexadecimal
7871 CR ." $" 2 U.R \ print IR_RC5 code
7872 ['] (CR) IS CR \ restore CR
7873 ['] (EMIT) IS EMIT \ restore EMIT
7874 HI2LO \ switch from FORTH to assembler
7875 \ ------------------------------\
7876 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
7877 \ ------------------------------\
7878 MOV @PSP+,&BASE \ restore variable BASE
7879 RETI \ CPU is ON, GIE is OFF
7884 \ ------------------------------\
7885 \ TB0CTL = %0000 0010 1001 0100\$3C0
7886 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7887 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7888 \ -- \ID input divider \ 10 = /4
7889 \ -- \MC Mode Control \ 01 = up to TB0CCR0
7890 \ - \TBCLR TimerB Clear
7893 \ --------------------------------\\
7894 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7895 \ -- \CM Capture Mode
7900 \ --- \OUTMOD \ 011 = set/reset
7906 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
7908 \ ------------------------------\
7909 \ set TimerB to make 50kHz PWM \
7910 \ ------------------------------\
7911 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7912 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
7913 \ ------------------------------\
7914 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
7915 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
7916 \ ------------------------------\
7917 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7918 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
7919 \ ------------------------------\
7920 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7921 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
7922 \ ------------------------------\
7923 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
7924 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
7925 \ ------------------------------\
7926 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
7927 \ ------------------------------\
7928 \ set TimerB to generate PWM for LCD_Vo
7929 \ ------------------------------\
7930 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
7931 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
7932 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7933 \ ------------------------------\
7934 BIS.B #LCDVo,&LCDVo_DIR \
7935 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
7936 \ ------------------------------\
7937 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7938 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7939 \ ------------------------------\
7940 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7941 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7942 \ ------------------------------\
7943 \ WDT interval init part \
7944 \ ------------------------------\
7945 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
7946 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
7947 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
7948 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
7949 \ ------------------------------\
7951 \ ------------------------------\
7952 BIS.B #RC5,&IR_IE \ enable RC5_Int
7953 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7954 \ ------------------------------\
7955 \ init interrupt vectors
7956 \ ------------------------------\
7957 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
7958 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7959 \ ------------------------------\
7960 \ define LPM mode for ACCEPT \
7961 \ ------------------------------\
7962 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7963 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7964 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7966 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
7968 \ ------------------------------\
7970 \ ------------------------------\
7971 $03E8 20_US \ 1- wait 20 ms
7972 $03 TOP_LCD \ 2- send DB5=DB4=1
7973 $CD 20_US \ 3- wait 4,1 ms
7974 $03 TOP_LCD \ 4- send again DB5=DB4=1
7975 $5 20_US \ 5- wait 0,1 ms
7976 $03 TOP_LCD \ 6- send again again DB5=DB4=1
7977 $2 20_US \ wait 40 us = LCD cycle
7978 $02 TOP_LCD \ 7- send DB5=1 DB4=0
7979 $2 20_US \ wait 40 us = LCD cycle
7980 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7981 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7982 LCD_Clear \ 10- "LCD_Clear"
7983 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7984 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7985 LCD_Clear \ 10- "LCD_Clear"
7986 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7987 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7989 ['] (CR) IS CR \ ' (CR) is CR
7990 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
7992 ." RC5toLCD is running. Type STOP to quit"
7993 \ NOECHO \ uncomment to run this app without terminal connexion
7994 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
7995 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
7999 : STOP \ stops multitasking, must to be used before downloading app
8000 ['] (WARM) IS WARM \ remove START app from FORTH init process
8001 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
8009 CODE MAX \ n1 n2 -- n3 signed maximum
8010 CMP @PSP,TOS \ n2-n1
8011 S< ?GOTO FW1 \ n2<n1
8017 CODE MIN \ n1 n2 -- n3 signed minimum
8018 CMP @PSP,TOS \ n2-n1
8019 S< ?GOTO BW1 \ n2<n1
8025 : U.R \ u n -- display u unsigned in n width (n >= 2)
8027 R> OVER - 0 MAX SPACES TYPE
8031 CODE 20_US \ n -- n * 20 us
8032 BEGIN \ 3 cycles loop + 6~
8033 \ MOV #5,W \ 3 MCLK = 1 MHz
8034 \ MOV #23,W \ 3 MCLK = 4 MHz
8035 MOV #51,W \ 3 MCLK = 8 MHz
8036 \ MOV #104,W \ 3 MCLK = 16 MHz
8037 \ MOV #158,W \ 3 MCLK = 24 MHz
8038 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
8048 CODE TOP_LCD \ LCD Sample
8049 \ \ if write : %xxxxWWWW --
8050 \ \ if read : -- %0000RRRR
8051 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8052 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8053 0= IF \ write LCD bits pattern
8055 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8056 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8059 THEN \ read LCD bits pattern
8062 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8063 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8069 CODE LCD_W \ byte -- write byte to LCD
8071 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8072 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8073 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8074 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8075 COLON \ high level word starts here
8076 TOP_LCD 2 20_US \ write high nibble first
8081 CODE LCD_WrC \ char -- Write Char
8082 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8087 CODE LCD_WrF \ func -- Write Fonction
8088 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8094 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
8099 $02 LCD_WrF 100 20_us
8103 \ : LCD_Entry_set $04 OR LCD_WrF ;
8105 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
8107 \ : LCD_Display_Shift $10 OR LCD_WrF ;
8109 \ : LCD_Fn_Set $20 OR LCD_WrF ;
8111 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
8113 \ : LCD_Goto $80 OR LCD_WrF ;
8115 \ CODE LCD_R \ -- byte read byte from LCD
8116 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8117 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8118 \ COLON \ starts a FORTH word
8119 \ TOP_LCD 2 20_us \ -- %0000HHHH
8120 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8121 \ HI2LO \ switch from FORTH to assembler
8122 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8123 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8124 \ MOV @RSP+,IP \ restore IP saved by COLON
8129 \ CODE LCD_RdS \ -- status Read Status
8130 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8135 \ CODE LCD_RdC \ -- char Read Char
8136 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8141 \ -------------+------+------+------+------++---+---+---+---+---------+
8142 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
8143 \ -------------+------+------+------+------++---+---+---+---+---------+
8144 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
8145 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
8146 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
8147 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
8148 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
8149 \ -------------+------+------+------+------++---+---+---+---+---------+
8152 \ ******************************\
8153 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8154 \ ******************************\
8155 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
8156 \ ------------------------------\
8157 \ define LPM mode for ACCEPT \
8158 \ ------------------------------\
8159 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8160 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8161 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8162 BIT.B #SW2,&SW2_IN \ test switch S2
8163 0= IF \ case of switch S2 pressed
8164 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
8166 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
8169 BIT.B #SW1,&SW1_IN \ test switch S1 input
8170 0= IF \ case of Switch S1 pressed
8171 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
8173 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
8177 RETI \ CPU is ON, GIE is OFF
8182 \ ------------------------------\
8183 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8184 \ ******************************\
8185 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8186 \ ******************************\
8187 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8188 \ \ SMclock = 8|16|24 MHz
8189 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
8190 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
8191 \ \ SR(9)=new Toggle bit memory (ADD on)
8192 \ ------------------------------\
8193 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
8194 \ ------------------------------\
8195 \ define LPM mode for ACCEPT \
8196 \ ------------------------------\
8197 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8198 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8199 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8200 \ ------------------------------\
8201 \ RC5_FirstStartBitHalfCycle: \
8202 \ ------------------------------\
8203 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
8204 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
8205 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
8206 MOV #1778,X \ RC5_Period in us
8207 MOV #14,W \ count of loop
8209 \ ------------------------------\
8210 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
8211 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
8212 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
8213 \ RC5_Compute_3/4_Period: \ |
8214 RRUM #1,X \ X=1/2 cycle |
8218 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
8219 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
8221 \ ------------------------------\
8222 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
8223 \ ------------------------------\
8224 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8225 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
8226 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8227 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8228 SUB #1,W \ decrement count loop
8229 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
8230 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8231 0<> WHILE \ ----> out of loop ----+
8232 \ RC5_compute_7/4_Time_out: \ |
8233 ADD X,Y \ | out of bound = 7/4 period
8234 \ RC5_WaitHalfCycleP1.2_IFG: \ |
8236 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
8237 0>= IF \ | if cycle time out of bound
8238 BIC #$30,&TA0CTL \ | stop timer_A0
8239 RETI \ | then quit to do nothing
8241 \ ------------------------------\ |
8242 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
8244 MOV &TA0R,X \ | | get new RC5_period value
8245 REPEAT \ ----> loop back --+ |
8246 \ ------------------------------\ |
8247 \ RC5_SampleEndOf: \ <---------------------+
8248 \ ------------------------------\
8249 BIC #$30,&TA0CTL \ stop timer_A0
8250 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
8251 \ ******************************\
8252 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8253 \ ******************************\
8254 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
8255 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
8256 XOR IP,X \ (new XOR old) Toggle bit (13)
8257 BIT #BIT13,X \ X(13) = New_RC5_command
8258 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
8260 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
8261 \ ******************************\
8262 \ RC5_ComputeNewRC5word \
8263 \ ******************************\
8265 MOV &BASE,2(PSP) \ save variable BASE before use
8266 MOV TOS,0(PSP) \ save TOS before use
8267 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
8268 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
8269 \ ******************************\
8270 \ RC5_ComputeC6bit \
8271 \ ******************************\
8272 BIT #$4000,IP \ test /C6 bit in IP
8273 0= IF BIS #$40,TOS \ set C6 bit in S
8274 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
8275 \ ******************************\
8276 \ RC5_CommandByteIsDone \ RC5_code --
8277 \ ******************************\
8279 \ ------------------------------\
8280 \ Display IR_RC5 code \
8281 \ ------------------------------\
8282 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
8283 \ ------------------------------\
8284 LO2HI \ switch from assembler to FORTH
8285 ['] LCD_CLEAR IS CR \ redirects CR
8286 ['] LCD_WrC IS EMIT \ redirects EMIT
8287 $10 BASE ! \ change BASE to hexadecimal
8288 CR ." $" 2 U.R \ print IR_RC5 code
8289 ['] (CR) IS CR \ restore CR
8290 ['] (EMIT) IS EMIT \ restore EMIT
8291 HI2LO \ switch from FORTH to assembler
8292 \ ------------------------------\
8293 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
8294 \ ------------------------------\
8295 MOV @PSP+,&BASE \ restore variable BASE
8296 RETI \ CPU is ON, GIE is OFF
8301 \ ------------------------------\
8302 \ TB0CTL = %0000 0010 1001 0100\$3C0
8303 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8304 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8305 \ -- \ID input divider \ 10 = /4
8306 \ -- \MC Mode Control \ 01 = up to TB0CCR0
8307 \ - \TBCLR TimerB Clear
8310 \ --------------------------------\\
8311 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8312 \ -- \CM Capture Mode
8317 \ --- \OUTMOD \ 011 = set/reset
8323 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
8325 \ ------------------------------\
8326 \ set TimerB to make 50kHz PWM \
8327 \ ------------------------------\
8328 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8329 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
8330 \ ------------------------------\
8331 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8332 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
8333 \ ------------------------------\
8334 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8335 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
8336 \ ------------------------------\
8337 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8338 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
8339 \ ------------------------------\
8340 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8341 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
8342 \ ------------------------------\
8343 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
8344 \ ------------------------------\
8345 \ set TimerB to generate PWM for LCD_Vo
8346 \ ------------------------------\
8347 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
8348 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
8349 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8350 \ ------------------------------\
8351 BIS.B #LCDVo,&LCDVo_DIR \
8352 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
8353 \ ------------------------------\
8354 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8355 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8356 \ ------------------------------\
8357 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8358 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8359 \ ------------------------------\
8360 \ WDT interval init part \
8361 \ ------------------------------\
8362 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
8363 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
8364 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
8365 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
8366 \ ------------------------------\
8368 \ ------------------------------\
8369 BIS.B #RC5,&IR_IE \ enable RC5_Int
8370 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8371 \ ------------------------------\
8372 \ init interrupt vectors
8373 \ ------------------------------\
8374 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
8375 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8376 \ ------------------------------\
8377 \ define LPM mode for ACCEPT \
8378 \ ------------------------------\
8379 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8380 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8381 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8383 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
8385 \ ------------------------------\
8387 \ ------------------------------\
8388 $03E8 20_US \ 1- wait 20 ms
8389 $03 TOP_LCD \ 2- send DB5=DB4=1
8390 $CD 20_US \ 3- wait 4,1 ms
8391 $03 TOP_LCD \ 4- send again DB5=DB4=1
8392 $5 20_US \ 5- wait 0,1 ms
8393 $03 TOP_LCD \ 6- send again again DB5=DB4=1
8394 $2 20_US \ wait 40 us = LCD cycle
8395 $02 TOP_LCD \ 7- send DB5=1 DB4=0
8396 $2 20_US \ wait 40 us = LCD cycle
8397 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8398 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8399 LCD_Clear \ 10- "LCD_Clear"
8400 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8401 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8402 LCD_Clear \ 10- "LCD_Clear"
8403 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8404 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8406 ['] (CR) IS CR \ ' (CR) is CR
8407 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
8409 ." RC5toLCD is running. Type STOP to quit"
8410 \ NOECHO \ uncomment to run this app without terminal connexion
8411 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
8412 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
8416 : STOP \ stops multitasking, must to be used before downloading app
8417 ['] (WARM) IS WARM \ remove START app from FORTH init process
8418 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
8426 CODE MAX \ n1 n2 -- n3 signed maximum
8427 CMP @PSP,TOS \ n2-n1
8428 S< ?GOTO FW1 \ n2<n1
8434 CODE MIN \ n1 n2 -- n3 signed minimum
8435 CMP @PSP,TOS \ n2-n1
8436 S< ?GOTO BW1 \ n2<n1
8442 : U.R \ u n -- display u unsigned in n width (n >= 2)
8444 R> OVER - 0 MAX SPACES TYPE
8448 CODE 20_US \ n -- n * 20 us
8449 BEGIN \ 3 cycles loop + 6~
8450 \ MOV #5,W \ 3 MCLK = 1 MHz
8451 \ MOV #23,W \ 3 MCLK = 4 MHz
8452 MOV #51,W \ 3 MCLK = 8 MHz
8453 \ MOV #104,W \ 3 MCLK = 16 MHz
8454 \ MOV #158,W \ 3 MCLK = 24 MHz
8455 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
8465 CODE TOP_LCD \ LCD Sample
8466 \ \ if write : %xxxxWWWW --
8467 \ \ if read : -- %0000RRRR
8468 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8469 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8470 0= IF \ write LCD bits pattern
8472 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8473 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8476 THEN \ read LCD bits pattern
8479 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8480 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8486 CODE LCD_W \ byte -- write byte to LCD
8488 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8489 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8490 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8491 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8492 COLON \ high level word starts here
8493 TOP_LCD 2 20_US \ write high nibble first
8498 CODE LCD_WrC \ char -- Write Char
8499 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8504 CODE LCD_WrF \ func -- Write Fonction
8505 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8511 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
8516 $02 LCD_WrF 100 20_us
8520 \ : LCD_Entry_set $04 OR LCD_WrF ;
8522 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
8524 \ : LCD_Display_Shift $10 OR LCD_WrF ;
8526 \ : LCD_Fn_Set $20 OR LCD_WrF ;
8528 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
8530 \ : LCD_Goto $80 OR LCD_WrF ;
8532 \ CODE LCD_R \ -- byte read byte from LCD
8533 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8534 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8535 \ COLON \ starts a FORTH word
8536 \ TOP_LCD 2 20_us \ -- %0000HHHH
8537 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8538 \ HI2LO \ switch from FORTH to assembler
8539 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8540 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8541 \ MOV @RSP+,IP \ restore IP saved by COLON
8546 \ CODE LCD_RdS \ -- status Read Status
8547 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8552 \ CODE LCD_RdC \ -- char Read Char
8553 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8558 \ -------------+------+------+------+------++---+---+---+---+---------+
8559 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
8560 \ -------------+------+------+------+------++---+---+---+---+---------+
8561 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
8562 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
8563 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
8564 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
8565 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
8566 \ -------------+------+------+------+------++---+---+---+---+---------+
8569 \ ******************************\
8570 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8571 \ ******************************\
8572 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
8573 \ ------------------------------\
8574 \ define LPM mode for ACCEPT \
8575 \ ------------------------------\
8576 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8577 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8578 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8579 BIT.B #SW2,&SW2_IN \ test switch S2
8580 0= IF \ case of switch S2 pressed
8581 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
8583 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
8586 BIT.B #SW1,&SW1_IN \ test switch S1 input
8587 0= IF \ case of Switch S1 pressed
8588 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
8590 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
8594 RETI \ CPU is ON, GIE is OFF
8599 \ ------------------------------\
8600 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8601 \ ******************************\
8602 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8603 \ ******************************\
8604 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8605 \ \ SMclock = 8|16|24 MHz
8606 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
8607 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
8608 \ \ SR(9)=new Toggle bit memory (ADD on)
8609 \ ------------------------------\
8610 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
8611 \ ------------------------------\
8612 \ define LPM mode for ACCEPT \
8613 \ ------------------------------\
8614 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8615 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8616 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8617 \ ------------------------------\
8618 \ RC5_FirstStartBitHalfCycle: \
8619 \ ------------------------------\
8620 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
8621 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
8622 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
8623 MOV #1778,X \ RC5_Period in us
8624 MOV #14,W \ count of loop
8626 \ ------------------------------\
8627 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
8628 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
8629 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
8630 \ RC5_Compute_3/4_Period: \ |
8631 RRUM #1,X \ X=1/2 cycle |
8635 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
8636 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
8638 \ ------------------------------\
8639 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
8640 \ ------------------------------\
8641 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8642 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
8643 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8644 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8645 SUB #1,W \ decrement count loop
8646 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
8647 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8648 0<> WHILE \ ----> out of loop ----+
8649 \ RC5_compute_7/4_Time_out: \ |
8650 ADD X,Y \ | out of bound = 7/4 period
8651 \ RC5_WaitHalfCycleP1.2_IFG: \ |
8653 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
8654 0>= IF \ | if cycle time out of bound
8655 BIC #$30,&TA0CTL \ | stop timer_A0
8656 RETI \ | then quit to do nothing
8658 \ ------------------------------\ |
8659 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
8661 MOV &TA0R,X \ | | get new RC5_period value
8662 REPEAT \ ----> loop back --+ |
8663 \ ------------------------------\ |
8664 \ RC5_SampleEndOf: \ <---------------------+
8665 \ ------------------------------\
8666 BIC #$30,&TA0CTL \ stop timer_A0
8667 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
8668 \ ******************************\
8669 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8670 \ ******************************\
8671 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
8672 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
8673 XOR IP,X \ (new XOR old) Toggle bit (13)
8674 BIT #BIT13,X \ X(13) = New_RC5_command
8675 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
8677 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
8678 \ ******************************\
8679 \ RC5_ComputeNewRC5word \
8680 \ ******************************\
8682 MOV &BASE,2(PSP) \ save variable BASE before use
8683 MOV TOS,0(PSP) \ save TOS before use
8684 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
8685 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
8686 \ ******************************\
8687 \ RC5_ComputeC6bit \
8688 \ ******************************\
8689 BIT #$4000,IP \ test /C6 bit in IP
8690 0= IF BIS #$40,TOS \ set C6 bit in S
8691 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
8692 \ ******************************\
8693 \ RC5_CommandByteIsDone \ RC5_code --
8694 \ ******************************\
8696 \ ------------------------------\
8697 \ Display IR_RC5 code \
8698 \ ------------------------------\
8699 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
8700 \ ------------------------------\
8701 LO2HI \ switch from assembler to FORTH
8702 ['] LCD_CLEAR IS CR \ redirects CR
8703 ['] LCD_WrC IS EMIT \ redirects EMIT
8704 $10 BASE ! \ change BASE to hexadecimal
8705 CR ." $" 2 U.R \ print IR_RC5 code
8706 ['] (CR) IS CR \ restore CR
8707 ['] (EMIT) IS EMIT \ restore EMIT
8708 HI2LO \ switch from FORTH to assembler
8709 \ ------------------------------\
8710 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
8711 \ ------------------------------\
8712 MOV @PSP+,&BASE \ restore variable BASE
8713 RETI \ CPU is ON, GIE is OFF
8718 \ ------------------------------\
8719 \ TB0CTL = %0000 0010 1001 0100\$3C0
8720 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8721 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8722 \ -- \ID input divider \ 10 = /4
8723 \ -- \MC Mode Control \ 01 = up to TB0CCR0
8724 \ - \TBCLR TimerB Clear
8727 \ --------------------------------\\
8728 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8729 \ -- \CM Capture Mode
8734 \ --- \OUTMOD \ 011 = set/reset
8740 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
8742 \ ------------------------------\
8743 \ set TimerB to make 50kHz PWM \
8744 \ ------------------------------\
8745 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8746 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
8747 \ ------------------------------\
8748 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
8749 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
8750 \ ------------------------------\
8751 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8752 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
8753 \ ------------------------------\
8754 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8755 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
8756 \ ------------------------------\
8757 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
8758 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
8759 \ ------------------------------\
8760 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
8761 \ ------------------------------\
8762 \ set TimerB to generate PWM for LCD_Vo
8763 \ ------------------------------\
8764 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
8765 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
8766 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8767 \ ------------------------------\
8768 BIS.B #LCDVo,&LCDVo_DIR \
8769 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
8770 \ ------------------------------\
8771 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8772 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8773 \ ------------------------------\
8774 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8775 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8776 \ ------------------------------\
8777 \ WDT interval init part \
8778 \ ------------------------------\
8779 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
8780 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
8781 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
8782 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
8783 \ ------------------------------\
8785 \ ------------------------------\
8786 BIS.B #RC5,&IR_IE \ enable RC5_Int
8787 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8788 \ ------------------------------\
8789 \ init interrupt vectors
8790 \ ------------------------------\
8791 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
8792 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8793 \ ------------------------------\
8794 \ define LPM mode for ACCEPT \
8795 \ ------------------------------\
8796 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8797 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8798 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8800 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
8802 \ ------------------------------\
8804 \ ------------------------------\
8805 $03E8 20_US \ 1- wait 20 ms
8806 $03 TOP_LCD \ 2- send DB5=DB4=1
8807 $CD 20_US \ 3- wait 4,1 ms
8808 $03 TOP_LCD \ 4- send again DB5=DB4=1
8809 $5 20_US \ 5- wait 0,1 ms
8810 $03 TOP_LCD \ 6- send again again DB5=DB4=1
8811 $2 20_US \ wait 40 us = LCD cycle
8812 $02 TOP_LCD \ 7- send DB5=1 DB4=0
8813 $2 20_US \ wait 40 us = LCD cycle
8814 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8815 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8816 LCD_Clear \ 10- "LCD_Clear"
8817 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8818 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8819 LCD_Clear \ 10- "LCD_Clear"
8820 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8821 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8823 ['] (CR) IS CR \ ' (CR) is CR
8824 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
8826 ." RC5toLCD is running. Type STOP to quit"
8827 \ NOECHO \ uncomment to run this app without terminal connexion
8828 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
8829 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
8833 : STOP \ stops multitasking, must to be used before downloading app
8834 ['] (WARM) IS WARM \ remove START app from FORTH init process
8835 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
8843 CODE MAX \ n1 n2 -- n3 signed maximum
8844 CMP @PSP,TOS \ n2-n1
8845 S< ?GOTO FW1 \ n2<n1
8851 CODE MIN \ n1 n2 -- n3 signed minimum
8852 CMP @PSP,TOS \ n2-n1
8853 S< ?GOTO BW1 \ n2<n1
8859 : U.R \ u n -- display u unsigned in n width (n >= 2)
8861 R> OVER - 0 MAX SPACES TYPE
8865 CODE 20_US \ n -- n * 20 us
8866 BEGIN \ 3 cycles loop + 6~
8867 \ MOV #5,W \ 3 MCLK = 1 MHz
8868 \ MOV #23,W \ 3 MCLK = 4 MHz
8869 MOV #51,W \ 3 MCLK = 8 MHz
8870 \ MOV #104,W \ 3 MCLK = 16 MHz
8871 \ MOV #158,W \ 3 MCLK = 24 MHz
8872 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
8882 CODE TOP_LCD \ LCD Sample
8883 \ \ if write : %xxxxWWWW --
8884 \ \ if read : -- %0000RRRR
8885 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8886 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8887 0= IF \ write LCD bits pattern
8889 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8890 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8893 THEN \ read LCD bits pattern
8896 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8897 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8903 CODE LCD_W \ byte -- write byte to LCD
8905 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
8906 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
8907 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8908 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8909 COLON \ high level word starts here
8910 TOP_LCD 2 20_US \ write high nibble first
8915 CODE LCD_WrC \ char -- Write Char
8916 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8921 CODE LCD_WrF \ func -- Write Fonction
8922 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8928 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
8933 $02 LCD_WrF 100 20_us
8937 \ : LCD_Entry_set $04 OR LCD_WrF ;
8939 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
8941 \ : LCD_Display_Shift $10 OR LCD_WrF ;
8943 \ : LCD_Fn_Set $20 OR LCD_WrF ;
8945 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
8947 \ : LCD_Goto $80 OR LCD_WrF ;
8949 \ CODE LCD_R \ -- byte read byte from LCD
8950 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8951 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8952 \ COLON \ starts a FORTH word
8953 \ TOP_LCD 2 20_us \ -- %0000HHHH
8954 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
8955 \ HI2LO \ switch from FORTH to assembler
8956 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
8957 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
8958 \ MOV @RSP+,IP \ restore IP saved by COLON
8963 \ CODE LCD_RdS \ -- status Read Status
8964 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8969 \ CODE LCD_RdC \ -- char Read Char
8970 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8975 \ -------------+------+------+------+------++---+---+---+---+---------+
8976 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
8977 \ -------------+------+------+------+------++---+---+---+---+---------+
8978 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
8979 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
8980 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
8981 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
8982 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
8983 \ -------------+------+------+------+------++---+---+---+---+---------+
8986 \ ******************************\
8987 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8988 \ ******************************\
8989 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
8990 \ ------------------------------\
8991 \ define LPM mode for ACCEPT \
8992 \ ------------------------------\
8993 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8994 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8995 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8996 BIT.B #SW2,&SW2_IN \ test switch S2
8997 0= IF \ case of switch S2 pressed
8998 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
9000 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
9003 BIT.B #SW1,&SW1_IN \ test switch S1 input
9004 0= IF \ case of Switch S1 pressed
9005 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
9007 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
9011 RETI \ CPU is ON, GIE is OFF
9016 \ ------------------------------\
9017 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9018 \ ******************************\
9019 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9020 \ ******************************\
9021 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9022 \ \ SMclock = 8|16|24 MHz
9023 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
9024 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
9025 \ \ SR(9)=new Toggle bit memory (ADD on)
9026 \ ------------------------------\
9027 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
9028 \ ------------------------------\
9029 \ define LPM mode for ACCEPT \
9030 \ ------------------------------\
9031 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9032 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9033 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9034 \ ------------------------------\
9035 \ RC5_FirstStartBitHalfCycle: \
9036 \ ------------------------------\
9037 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
9038 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
9039 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
9040 MOV #1778,X \ RC5_Period in us
9041 MOV #14,W \ count of loop
9043 \ ------------------------------\
9044 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
9045 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
9046 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
9047 \ RC5_Compute_3/4_Period: \ |
9048 RRUM #1,X \ X=1/2 cycle |
9052 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
9053 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
9055 \ ------------------------------\
9056 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
9057 \ ------------------------------\
9058 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9059 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
9060 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9061 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9062 SUB #1,W \ decrement count loop
9063 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
9064 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9065 0<> WHILE \ ----> out of loop ----+
9066 \ RC5_compute_7/4_Time_out: \ |
9067 ADD X,Y \ | out of bound = 7/4 period
9068 \ RC5_WaitHalfCycleP1.2_IFG: \ |
9070 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
9071 0>= IF \ | if cycle time out of bound
9072 BIC #$30,&TA0CTL \ | stop timer_A0
9073 RETI \ | then quit to do nothing
9075 \ ------------------------------\ |
9076 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
9078 MOV &TA0R,X \ | | get new RC5_period value
9079 REPEAT \ ----> loop back --+ |
9080 \ ------------------------------\ |
9081 \ RC5_SampleEndOf: \ <---------------------+
9082 \ ------------------------------\
9083 BIC #$30,&TA0CTL \ stop timer_A0
9084 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
9085 \ ******************************\
9086 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9087 \ ******************************\
9088 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
9089 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
9090 XOR IP,X \ (new XOR old) Toggle bit (13)
9091 BIT #BIT13,X \ X(13) = New_RC5_command
9092 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
9094 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
9095 \ ******************************\
9096 \ RC5_ComputeNewRC5word \
9097 \ ******************************\
9099 MOV &BASE,2(PSP) \ save variable BASE before use
9100 MOV TOS,0(PSP) \ save TOS before use
9101 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
9102 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
9103 \ ******************************\
9104 \ RC5_ComputeC6bit \
9105 \ ******************************\
9106 BIT #$4000,IP \ test /C6 bit in IP
9107 0= IF BIS #$40,TOS \ set C6 bit in S
9108 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
9109 \ ******************************\
9110 \ RC5_CommandByteIsDone \ RC5_code --
9111 \ ******************************\
9113 \ ------------------------------\
9114 \ Display IR_RC5 code \
9115 \ ------------------------------\
9116 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
9117 \ ------------------------------\
9118 LO2HI \ switch from assembler to FORTH
9119 ['] LCD_CLEAR IS CR \ redirects CR
9120 ['] LCD_WrC IS EMIT \ redirects EMIT
9121 $10 BASE ! \ change BASE to hexadecimal
9122 CR ." $" 2 U.R \ print IR_RC5 code
9123 ['] (CR) IS CR \ restore CR
9124 ['] (EMIT) IS EMIT \ restore EMIT
9125 HI2LO \ switch from FORTH to assembler
9126 \ ------------------------------\
9127 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
9128 \ ------------------------------\
9129 MOV @PSP+,&BASE \ restore variable BASE
9130 RETI \ CPU is ON, GIE is OFF
9135 \ ------------------------------\
9136 \ TB0CTL = %0000 0010 1001 0100\$3C0
9137 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9138 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9139 \ -- \ID input divider \ 10 = /4
9140 \ -- \MC Mode Control \ 01 = up to TB0CCR0
9141 \ - \TBCLR TimerB Clear
9144 \ --------------------------------\\
9145 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9146 \ -- \CM Capture Mode
9151 \ --- \OUTMOD \ 011 = set/reset
9157 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
9159 \ ------------------------------\
9160 \ set TimerB to make 50kHz PWM \
9161 \ ------------------------------\
9162 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9163 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
9164 \ ------------------------------\
9165 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9166 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
9167 \ ------------------------------\
9168 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9169 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
9170 \ ------------------------------\
9171 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9172 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
9173 \ ------------------------------\
9174 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9175 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
9176 \ ------------------------------\
9177 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
9178 \ ------------------------------\
9179 \ set TimerB to generate PWM for LCD_Vo
9180 \ ------------------------------\
9181 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
9182 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
9183 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9184 \ ------------------------------\
9185 BIS.B #LCDVo,&LCDVo_DIR \
9186 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
9187 \ ------------------------------\
9188 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9189 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9190 \ ------------------------------\
9191 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9192 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9193 \ ------------------------------\
9194 \ WDT interval init part \
9195 \ ------------------------------\
9196 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
9197 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
9198 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
9199 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
9200 \ ------------------------------\
9202 \ ------------------------------\
9203 BIS.B #RC5,&IR_IE \ enable RC5_Int
9204 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9205 \ ------------------------------\
9206 \ init interrupt vectors
9207 \ ------------------------------\
9208 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
9209 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9210 \ ------------------------------\
9211 \ define LPM mode for ACCEPT \
9212 \ ------------------------------\
9213 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9214 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9215 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9217 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
9219 \ ------------------------------\
9221 \ ------------------------------\
9222 $03E8 20_US \ 1- wait 20 ms
9223 $03 TOP_LCD \ 2- send DB5=DB4=1
9224 $CD 20_US \ 3- wait 4,1 ms
9225 $03 TOP_LCD \ 4- send again DB5=DB4=1
9226 $5 20_US \ 5- wait 0,1 ms
9227 $03 TOP_LCD \ 6- send again again DB5=DB4=1
9228 $2 20_US \ wait 40 us = LCD cycle
9229 $02 TOP_LCD \ 7- send DB5=1 DB4=0
9230 $2 20_US \ wait 40 us = LCD cycle
9231 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9232 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9233 LCD_Clear \ 10- "LCD_Clear"
9234 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9235 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9236 LCD_Clear \ 10- "LCD_Clear"
9237 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9238 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9240 ['] (CR) IS CR \ ' (CR) is CR
9241 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
9243 ." RC5toLCD is running. Type STOP to quit"
9244 \ NOECHO \ uncomment to run this app without terminal connexion
9245 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
9246 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
9250 : STOP \ stops multitasking, must to be used before downloading app
9251 ['] (WARM) IS WARM \ remove START app from FORTH init process
9252 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
9260 CODE MAX \ n1 n2 -- n3 signed maximum
9261 CMP @PSP,TOS \ n2-n1
9262 S< ?GOTO FW1 \ n2<n1
9268 CODE MIN \ n1 n2 -- n3 signed minimum
9269 CMP @PSP,TOS \ n2-n1
9270 S< ?GOTO BW1 \ n2<n1
9276 : U.R \ u n -- display u unsigned in n width (n >= 2)
9278 R> OVER - 0 MAX SPACES TYPE
9282 CODE 20_US \ n -- n * 20 us
9283 BEGIN \ 3 cycles loop + 6~
9284 \ MOV #5,W \ 3 MCLK = 1 MHz
9285 \ MOV #23,W \ 3 MCLK = 4 MHz
9286 MOV #51,W \ 3 MCLK = 8 MHz
9287 \ MOV #104,W \ 3 MCLK = 16 MHz
9288 \ MOV #158,W \ 3 MCLK = 24 MHz
9289 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
9299 CODE TOP_LCD \ LCD Sample
9300 \ \ if write : %xxxxWWWW --
9301 \ \ if read : -- %0000RRRR
9302 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9303 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9304 0= IF \ write LCD bits pattern
9306 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9307 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9310 THEN \ read LCD bits pattern
9313 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9314 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9320 CODE LCD_W \ byte -- write byte to LCD
9322 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9323 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9324 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9325 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9326 COLON \ high level word starts here
9327 TOP_LCD 2 20_US \ write high nibble first
9332 CODE LCD_WrC \ char -- Write Char
9333 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9338 CODE LCD_WrF \ func -- Write Fonction
9339 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9345 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
9350 $02 LCD_WrF 100 20_us
9354 \ : LCD_Entry_set $04 OR LCD_WrF ;
9356 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
9358 \ : LCD_Display_Shift $10 OR LCD_WrF ;
9360 \ : LCD_Fn_Set $20 OR LCD_WrF ;
9362 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
9364 \ : LCD_Goto $80 OR LCD_WrF ;
9366 \ CODE LCD_R \ -- byte read byte from LCD
9367 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9368 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9369 \ COLON \ starts a FORTH word
9370 \ TOP_LCD 2 20_us \ -- %0000HHHH
9371 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9372 \ HI2LO \ switch from FORTH to assembler
9373 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9374 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9375 \ MOV @RSP+,IP \ restore IP saved by COLON
9380 \ CODE LCD_RdS \ -- status Read Status
9381 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9386 \ CODE LCD_RdC \ -- char Read Char
9387 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9392 \ -------------+------+------+------+------++---+---+---+---+---------+
9393 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
9394 \ -------------+------+------+------+------++---+---+---+---+---------+
9395 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
9396 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
9397 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
9398 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
9399 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
9400 \ -------------+------+------+------+------++---+---+---+---+---------+
9403 \ ******************************\
9404 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9405 \ ******************************\
9406 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
9407 \ ------------------------------\
9408 \ define LPM mode for ACCEPT \
9409 \ ------------------------------\
9410 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9411 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9412 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9413 BIT.B #SW2,&SW2_IN \ test switch S2
9414 0= IF \ case of switch S2 pressed
9415 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
9417 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
9420 BIT.B #SW1,&SW1_IN \ test switch S1 input
9421 0= IF \ case of Switch S1 pressed
9422 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
9424 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
9428 RETI \ CPU is ON, GIE is OFF
9433 \ ------------------------------\
9434 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9435 \ ******************************\
9436 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9437 \ ******************************\
9438 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9439 \ \ SMclock = 8|16|24 MHz
9440 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
9441 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
9442 \ \ SR(9)=new Toggle bit memory (ADD on)
9443 \ ------------------------------\
9444 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
9445 \ ------------------------------\
9446 \ define LPM mode for ACCEPT \
9447 \ ------------------------------\
9448 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9449 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9450 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9451 \ ------------------------------\
9452 \ RC5_FirstStartBitHalfCycle: \
9453 \ ------------------------------\
9454 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
9455 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
9456 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
9457 MOV #1778,X \ RC5_Period in us
9458 MOV #14,W \ count of loop
9460 \ ------------------------------\
9461 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
9462 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
9463 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
9464 \ RC5_Compute_3/4_Period: \ |
9465 RRUM #1,X \ X=1/2 cycle |
9469 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
9470 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
9472 \ ------------------------------\
9473 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
9474 \ ------------------------------\
9475 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9476 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
9477 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9478 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9479 SUB #1,W \ decrement count loop
9480 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
9481 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9482 0<> WHILE \ ----> out of loop ----+
9483 \ RC5_compute_7/4_Time_out: \ |
9484 ADD X,Y \ | out of bound = 7/4 period
9485 \ RC5_WaitHalfCycleP1.2_IFG: \ |
9487 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
9488 0>= IF \ | if cycle time out of bound
9489 BIC #$30,&TA0CTL \ | stop timer_A0
9490 RETI \ | then quit to do nothing
9492 \ ------------------------------\ |
9493 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
9495 MOV &TA0R,X \ | | get new RC5_period value
9496 REPEAT \ ----> loop back --+ |
9497 \ ------------------------------\ |
9498 \ RC5_SampleEndOf: \ <---------------------+
9499 \ ------------------------------\
9500 BIC #$30,&TA0CTL \ stop timer_A0
9501 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
9502 \ ******************************\
9503 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9504 \ ******************************\
9505 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
9506 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
9507 XOR IP,X \ (new XOR old) Toggle bit (13)
9508 BIT #BIT13,X \ X(13) = New_RC5_command
9509 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
9511 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
9512 \ ******************************\
9513 \ RC5_ComputeNewRC5word \
9514 \ ******************************\
9516 MOV &BASE,2(PSP) \ save variable BASE before use
9517 MOV TOS,0(PSP) \ save TOS before use
9518 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
9519 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
9520 \ ******************************\
9521 \ RC5_ComputeC6bit \
9522 \ ******************************\
9523 BIT #$4000,IP \ test /C6 bit in IP
9524 0= IF BIS #$40,TOS \ set C6 bit in S
9525 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
9526 \ ******************************\
9527 \ RC5_CommandByteIsDone \ RC5_code --
9528 \ ******************************\
9530 \ ------------------------------\
9531 \ Display IR_RC5 code \
9532 \ ------------------------------\
9533 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
9534 \ ------------------------------\
9535 LO2HI \ switch from assembler to FORTH
9536 ['] LCD_CLEAR IS CR \ redirects CR
9537 ['] LCD_WrC IS EMIT \ redirects EMIT
9538 $10 BASE ! \ change BASE to hexadecimal
9539 CR ." $" 2 U.R \ print IR_RC5 code
9540 ['] (CR) IS CR \ restore CR
9541 ['] (EMIT) IS EMIT \ restore EMIT
9542 HI2LO \ switch from FORTH to assembler
9543 \ ------------------------------\
9544 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
9545 \ ------------------------------\
9546 MOV @PSP+,&BASE \ restore variable BASE
9547 RETI \ CPU is ON, GIE is OFF
9552 \ ------------------------------\
9553 \ TB0CTL = %0000 0010 1001 0100\$3C0
9554 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9555 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9556 \ -- \ID input divider \ 10 = /4
9557 \ -- \MC Mode Control \ 01 = up to TB0CCR0
9558 \ - \TBCLR TimerB Clear
9561 \ --------------------------------\\
9562 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9563 \ -- \CM Capture Mode
9568 \ --- \OUTMOD \ 011 = set/reset
9574 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
9576 \ ------------------------------\
9577 \ set TimerB to make 50kHz PWM \
9578 \ ------------------------------\
9579 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9580 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
9581 \ ------------------------------\
9582 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9583 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
9584 \ ------------------------------\
9585 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9586 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
9587 \ ------------------------------\
9588 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9589 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
9590 \ ------------------------------\
9591 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
9592 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
9593 \ ------------------------------\
9594 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
9595 \ ------------------------------\
9596 \ set TimerB to generate PWM for LCD_Vo
9597 \ ------------------------------\
9598 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
9599 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
9600 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9601 \ ------------------------------\
9602 BIS.B #LCDVo,&LCDVo_DIR \
9603 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
9604 \ ------------------------------\
9605 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9606 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9607 \ ------------------------------\
9608 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9609 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9610 \ ------------------------------\
9611 \ WDT interval init part \
9612 \ ------------------------------\
9613 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
9614 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
9615 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
9616 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
9617 \ ------------------------------\
9619 \ ------------------------------\
9620 BIS.B #RC5,&IR_IE \ enable RC5_Int
9621 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9622 \ ------------------------------\
9623 \ init interrupt vectors
9624 \ ------------------------------\
9625 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
9626 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9627 \ ------------------------------\
9628 \ define LPM mode for ACCEPT \
9629 \ ------------------------------\
9630 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9631 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9632 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9634 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
9636 \ ------------------------------\
9638 \ ------------------------------\
9639 $03E8 20_US \ 1- wait 20 ms
9640 $03 TOP_LCD \ 2- send DB5=DB4=1
9641 $CD 20_US \ 3- wait 4,1 ms
9642 $03 TOP_LCD \ 4- send again DB5=DB4=1
9643 $5 20_US \ 5- wait 0,1 ms
9644 $03 TOP_LCD \ 6- send again again DB5=DB4=1
9645 $2 20_US \ wait 40 us = LCD cycle
9646 $02 TOP_LCD \ 7- send DB5=1 DB4=0
9647 $2 20_US \ wait 40 us = LCD cycle
9648 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9649 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9650 LCD_Clear \ 10- "LCD_Clear"
9651 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9652 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9653 LCD_Clear \ 10- "LCD_Clear"
9654 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9655 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9657 ['] (CR) IS CR \ ' (CR) is CR
9658 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
9660 ." RC5toLCD is running. Type STOP to quit"
9661 \ NOECHO \ uncomment to run this app without terminal connexion
9662 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
9663 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
9667 : STOP \ stops multitasking, must to be used before downloading app
9668 ['] (WARM) IS WARM \ remove START app from FORTH init process
9669 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
9677 CODE MAX \ n1 n2 -- n3 signed maximum
9678 CMP @PSP,TOS \ n2-n1
9679 S< ?GOTO FW1 \ n2<n1
9685 CODE MIN \ n1 n2 -- n3 signed minimum
9686 CMP @PSP,TOS \ n2-n1
9687 S< ?GOTO BW1 \ n2<n1
9693 : U.R \ u n -- display u unsigned in n width (n >= 2)
9695 R> OVER - 0 MAX SPACES TYPE
9699 CODE 20_US \ n -- n * 20 us
9700 BEGIN \ 3 cycles loop + 6~
9701 \ MOV #5,W \ 3 MCLK = 1 MHz
9702 \ MOV #23,W \ 3 MCLK = 4 MHz
9703 MOV #51,W \ 3 MCLK = 8 MHz
9704 \ MOV #104,W \ 3 MCLK = 16 MHz
9705 \ MOV #158,W \ 3 MCLK = 24 MHz
9706 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
9716 CODE TOP_LCD \ LCD Sample
9717 \ \ if write : %xxxxWWWW --
9718 \ \ if read : -- %0000RRRR
9719 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9720 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9721 0= IF \ write LCD bits pattern
9723 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9724 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9727 THEN \ read LCD bits pattern
9730 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9731 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9737 CODE LCD_W \ byte -- write byte to LCD
9739 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
9740 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
9741 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9742 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9743 COLON \ high level word starts here
9744 TOP_LCD 2 20_US \ write high nibble first
9749 CODE LCD_WrC \ char -- Write Char
9750 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9755 CODE LCD_WrF \ func -- Write Fonction
9756 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9762 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
9767 $02 LCD_WrF 100 20_us
9771 \ : LCD_Entry_set $04 OR LCD_WrF ;
9773 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
9775 \ : LCD_Display_Shift $10 OR LCD_WrF ;
9777 \ : LCD_Fn_Set $20 OR LCD_WrF ;
9779 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
9781 \ : LCD_Goto $80 OR LCD_WrF ;
9783 \ CODE LCD_R \ -- byte read byte from LCD
9784 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9785 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9786 \ COLON \ starts a FORTH word
9787 \ TOP_LCD 2 20_us \ -- %0000HHHH
9788 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
9789 \ HI2LO \ switch from FORTH to assembler
9790 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
9791 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
9792 \ MOV @RSP+,IP \ restore IP saved by COLON
9797 \ CODE LCD_RdS \ -- status Read Status
9798 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9803 \ CODE LCD_RdC \ -- char Read Char
9804 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9809 \ -------------+------+------+------+------++---+---+---+---+---------+
9810 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
9811 \ -------------+------+------+------+------++---+---+---+---+---------+
9812 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
9813 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
9814 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
9815 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
9816 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
9817 \ -------------+------+------+------+------++---+---+---+---+---------+
9820 \ ******************************\
9821 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9822 \ ******************************\
9823 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
9824 \ ------------------------------\
9825 \ define LPM mode for ACCEPT \
9826 \ ------------------------------\
9827 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9828 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9829 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9830 BIT.B #SW2,&SW2_IN \ test switch S2
9831 0= IF \ case of switch S2 pressed
9832 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
9834 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
9837 BIT.B #SW1,&SW1_IN \ test switch S1 input
9838 0= IF \ case of Switch S1 pressed
9839 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
9841 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
9845 RETI \ CPU is ON, GIE is OFF
9850 \ ------------------------------\
9851 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9852 \ ******************************\
9853 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9854 \ ******************************\
9855 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9856 \ \ SMclock = 8|16|24 MHz
9857 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
9858 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
9859 \ \ SR(9)=new Toggle bit memory (ADD on)
9860 \ ------------------------------\
9861 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
9862 \ ------------------------------\
9863 \ define LPM mode for ACCEPT \
9864 \ ------------------------------\
9865 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9866 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9867 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9868 \ ------------------------------\
9869 \ RC5_FirstStartBitHalfCycle: \
9870 \ ------------------------------\
9871 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
9872 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
9873 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
9874 MOV #1778,X \ RC5_Period in us
9875 MOV #14,W \ count of loop
9877 \ ------------------------------\
9878 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
9879 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
9880 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
9881 \ RC5_Compute_3/4_Period: \ |
9882 RRUM #1,X \ X=1/2 cycle |
9886 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
9887 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
9889 \ ------------------------------\
9890 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
9891 \ ------------------------------\
9892 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9893 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
9894 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9895 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9896 SUB #1,W \ decrement count loop
9897 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
9898 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9899 0<> WHILE \ ----> out of loop ----+
9900 \ RC5_compute_7/4_Time_out: \ |
9901 ADD X,Y \ | out of bound = 7/4 period
9902 \ RC5_WaitHalfCycleP1.2_IFG: \ |
9904 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
9905 0>= IF \ | if cycle time out of bound
9906 BIC #$30,&TA0CTL \ | stop timer_A0
9907 RETI \ | then quit to do nothing
9909 \ ------------------------------\ |
9910 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
9912 MOV &TA0R,X \ | | get new RC5_period value
9913 REPEAT \ ----> loop back --+ |
9914 \ ------------------------------\ |
9915 \ RC5_SampleEndOf: \ <---------------------+
9916 \ ------------------------------\
9917 BIC #$30,&TA0CTL \ stop timer_A0
9918 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
9919 \ ******************************\
9920 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9921 \ ******************************\
9922 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
9923 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
9924 XOR IP,X \ (new XOR old) Toggle bit (13)
9925 BIT #BIT13,X \ X(13) = New_RC5_command
9926 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
9928 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
9929 \ ******************************\
9930 \ RC5_ComputeNewRC5word \
9931 \ ******************************\
9933 MOV &BASE,2(PSP) \ save variable BASE before use
9934 MOV TOS,0(PSP) \ save TOS before use
9935 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
9936 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
9937 \ ******************************\
9938 \ RC5_ComputeC6bit \
9939 \ ******************************\
9940 BIT #$4000,IP \ test /C6 bit in IP
9941 0= IF BIS #$40,TOS \ set C6 bit in S
9942 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
9943 \ ******************************\
9944 \ RC5_CommandByteIsDone \ RC5_code --
9945 \ ******************************\
9947 \ ------------------------------\
9948 \ Display IR_RC5 code \
9949 \ ------------------------------\
9950 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
9951 \ ------------------------------\
9952 LO2HI \ switch from assembler to FORTH
9953 ['] LCD_CLEAR IS CR \ redirects CR
9954 ['] LCD_WrC IS EMIT \ redirects EMIT
9955 $10 BASE ! \ change BASE to hexadecimal
9956 CR ." $" 2 U.R \ print IR_RC5 code
9957 ['] (CR) IS CR \ restore CR
9958 ['] (EMIT) IS EMIT \ restore EMIT
9959 HI2LO \ switch from FORTH to assembler
9960 \ ------------------------------\
9961 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
9962 \ ------------------------------\
9963 MOV @PSP+,&BASE \ restore variable BASE
9964 RETI \ CPU is ON, GIE is OFF
9969 \ ------------------------------\
9970 \ TB0CTL = %0000 0010 1001 0100\$3C0
9971 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9972 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9973 \ -- \ID input divider \ 10 = /4
9974 \ -- \MC Mode Control \ 01 = up to TB0CCR0
9975 \ - \TBCLR TimerB Clear
9978 \ --------------------------------\\
9979 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9980 \ -- \CM Capture Mode
9985 \ --- \OUTMOD \ 011 = set/reset
9991 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
9993 \ ------------------------------\
9994 \ set TimerB to make 50kHz PWM \
9995 \ ------------------------------\
9996 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
9997 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
9998 \ ------------------------------\
9999 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10000 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
10001 \ ------------------------------\
10002 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10003 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
10004 \ ------------------------------\
10005 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10006 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
10007 \ ------------------------------\
10008 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10009 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
10010 \ ------------------------------\
10011 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
10012 \ ------------------------------\
10013 \ set TimerB to generate PWM for LCD_Vo
10014 \ ------------------------------\
10015 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
10016 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
10017 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10018 \ ------------------------------\
10019 BIS.B #LCDVo,&LCDVo_DIR \
10020 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
10021 \ ------------------------------\
10022 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10023 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10024 \ ------------------------------\
10025 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10026 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10027 \ ------------------------------\
10028 \ WDT interval init part \
10029 \ ------------------------------\
10030 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
10031 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
10032 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
10033 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
10034 \ ------------------------------\
10036 \ ------------------------------\
10037 BIS.B #RC5,&IR_IE \ enable RC5_Int
10038 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10039 \ ------------------------------\
10040 \ init interrupt vectors
10041 \ ------------------------------\
10042 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
10043 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10044 \ ------------------------------\
10045 \ define LPM mode for ACCEPT \
10046 \ ------------------------------\
10047 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10048 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10049 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10051 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
10053 \ ------------------------------\
10055 \ ------------------------------\
10056 $03E8 20_US \ 1- wait 20 ms
10057 $03 TOP_LCD \ 2- send DB5=DB4=1
10058 $CD 20_US \ 3- wait 4,1 ms
10059 $03 TOP_LCD \ 4- send again DB5=DB4=1
10060 $5 20_US \ 5- wait 0,1 ms
10061 $03 TOP_LCD \ 6- send again again DB5=DB4=1
10062 $2 20_US \ wait 40 us = LCD cycle
10063 $02 TOP_LCD \ 7- send DB5=1 DB4=0
10064 $2 20_US \ wait 40 us = LCD cycle
10065 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10066 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10067 LCD_Clear \ 10- "LCD_Clear"
10068 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10069 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10070 LCD_Clear \ 10- "LCD_Clear"
10071 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10072 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10074 ['] (CR) IS CR \ ' (CR) is CR
10075 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
10077 ." RC5toLCD is running. Type STOP to quit"
10078 \ NOECHO \ uncomment to run this app without terminal connexion
10079 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
10080 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
10084 : STOP \ stops multitasking, must to be used before downloading app
10085 ['] (WARM) IS WARM \ remove START app from FORTH init process
10086 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
10094 CODE MAX \ n1 n2 -- n3 signed maximum
10095 CMP @PSP,TOS \ n2-n1
10096 S< ?GOTO FW1 \ n2<n1
10102 CODE MIN \ n1 n2 -- n3 signed minimum
10103 CMP @PSP,TOS \ n2-n1
10104 S< ?GOTO BW1 \ n2<n1
10110 : U.R \ u n -- display u unsigned in n width (n >= 2)
10112 R> OVER - 0 MAX SPACES TYPE
10116 CODE 20_US \ n -- n * 20 us
10117 BEGIN \ 3 cycles loop + 6~
10118 \ MOV #5,W \ 3 MCLK = 1 MHz
10119 \ MOV #23,W \ 3 MCLK = 4 MHz
10120 MOV #51,W \ 3 MCLK = 8 MHz
10121 \ MOV #104,W \ 3 MCLK = 16 MHz
10122 \ MOV #158,W \ 3 MCLK = 24 MHz
10123 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
10133 CODE TOP_LCD \ LCD Sample
10134 \ \ if write : %xxxxWWWW --
10135 \ \ if read : -- %0000RRRR
10136 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10137 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10138 0= IF \ write LCD bits pattern
10139 AND.B #LCD_DB,TOS \
10140 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10141 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10144 THEN \ read LCD bits pattern
10147 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10148 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10149 AND.B #LCD_DB,TOS \
10154 CODE LCD_W \ byte -- write byte to LCD
10156 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10157 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10158 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10159 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10160 COLON \ high level word starts here
10161 TOP_LCD 2 20_US \ write high nibble first
10166 CODE LCD_WrC \ char -- Write Char
10167 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10172 CODE LCD_WrF \ func -- Write Fonction
10173 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10179 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
10184 $02 LCD_WrF 100 20_us
10188 \ : LCD_Entry_set $04 OR LCD_WrF ;
10190 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
10192 \ : LCD_Display_Shift $10 OR LCD_WrF ;
10194 \ : LCD_Fn_Set $20 OR LCD_WrF ;
10196 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
10198 \ : LCD_Goto $80 OR LCD_WrF ;
10200 \ CODE LCD_R \ -- byte read byte from LCD
10201 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10202 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10203 \ COLON \ starts a FORTH word
10204 \ TOP_LCD 2 20_us \ -- %0000HHHH
10205 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
10206 \ HI2LO \ switch from FORTH to assembler
10207 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
10208 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
10209 \ MOV @RSP+,IP \ restore IP saved by COLON
10214 \ CODE LCD_RdS \ -- status Read Status
10215 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10220 \ CODE LCD_RdC \ -- char Read Char
10221 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10226 \ -------------+------+------+------+------++---+---+---+---+---------+
10227 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
10228 \ -------------+------+------+------+------++---+---+---+---+---------+
10229 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
10230 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
10231 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
10232 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
10233 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
10234 \ -------------+------+------+------+------++---+---+---+---+---------+
10237 \ ******************************\
10238 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10239 \ ******************************\
10240 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
10241 \ ------------------------------\
10242 \ define LPM mode for ACCEPT \
10243 \ ------------------------------\
10244 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10245 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10246 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10247 BIT.B #SW2,&SW2_IN \ test switch S2
10248 0= IF \ case of switch S2 pressed
10249 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
10251 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
10254 BIT.B #SW1,&SW1_IN \ test switch S1 input
10255 0= IF \ case of Switch S1 pressed
10256 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
10258 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
10262 RETI \ CPU is ON, GIE is OFF
10267 \ ------------------------------\
10268 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10269 \ ******************************\
10270 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10271 \ ******************************\
10272 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10273 \ \ SMclock = 8|16|24 MHz
10274 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
10275 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
10276 \ \ SR(9)=new Toggle bit memory (ADD on)
10277 \ ------------------------------\
10278 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
10279 \ ------------------------------\
10280 \ define LPM mode for ACCEPT \
10281 \ ------------------------------\
10282 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10283 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10284 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10285 \ ------------------------------\
10286 \ RC5_FirstStartBitHalfCycle: \
10287 \ ------------------------------\
10288 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
10289 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
10290 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
10291 MOV #1778,X \ RC5_Period in us
10292 MOV #14,W \ count of loop
10294 \ ------------------------------\
10295 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
10296 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
10297 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
10298 \ RC5_Compute_3/4_Period: \ |
10299 RRUM #1,X \ X=1/2 cycle |
10303 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
10304 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
10306 \ ------------------------------\
10307 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
10308 \ ------------------------------\
10309 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10310 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
10311 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10312 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10313 SUB #1,W \ decrement count loop
10314 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
10315 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10316 0<> WHILE \ ----> out of loop ----+
10317 \ RC5_compute_7/4_Time_out: \ |
10318 ADD X,Y \ | out of bound = 7/4 period
10319 \ RC5_WaitHalfCycleP1.2_IFG: \ |
10321 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
10322 0>= IF \ | if cycle time out of bound
10323 BIC #$30,&TA0CTL \ | stop timer_A0
10324 RETI \ | then quit to do nothing
10326 \ ------------------------------\ |
10327 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
10329 MOV &TA0R,X \ | | get new RC5_period value
10330 REPEAT \ ----> loop back --+ |
10331 \ ------------------------------\ |
10332 \ RC5_SampleEndOf: \ <---------------------+
10333 \ ------------------------------\
10334 BIC #$30,&TA0CTL \ stop timer_A0
10335 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
10336 \ ******************************\
10337 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10338 \ ******************************\
10339 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
10340 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
10341 XOR IP,X \ (new XOR old) Toggle bit (13)
10342 BIT #BIT13,X \ X(13) = New_RC5_command
10343 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
10345 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
10346 \ ******************************\
10347 \ RC5_ComputeNewRC5word \
10348 \ ******************************\
10350 MOV &BASE,2(PSP) \ save variable BASE before use
10351 MOV TOS,0(PSP) \ save TOS before use
10352 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
10353 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
10354 \ ******************************\
10355 \ RC5_ComputeC6bit \
10356 \ ******************************\
10357 BIT #$4000,IP \ test /C6 bit in IP
10358 0= IF BIS #$40,TOS \ set C6 bit in S
10359 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
10360 \ ******************************\
10361 \ RC5_CommandByteIsDone \ RC5_code --
10362 \ ******************************\
10364 \ ------------------------------\
10365 \ Display IR_RC5 code \
10366 \ ------------------------------\
10367 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
10368 \ ------------------------------\
10369 LO2HI \ switch from assembler to FORTH
10370 ['] LCD_CLEAR IS CR \ redirects CR
10371 ['] LCD_WrC IS EMIT \ redirects EMIT
10372 $10 BASE ! \ change BASE to hexadecimal
10373 CR ." $" 2 U.R \ print IR_RC5 code
10374 ['] (CR) IS CR \ restore CR
10375 ['] (EMIT) IS EMIT \ restore EMIT
10376 HI2LO \ switch from FORTH to assembler
10377 \ ------------------------------\
10378 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
10379 \ ------------------------------\
10380 MOV @PSP+,&BASE \ restore variable BASE
10381 RETI \ CPU is ON, GIE is OFF
10386 \ ------------------------------\
10387 \ TB0CTL = %0000 0010 1001 0100\$3C0
10388 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10389 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10390 \ -- \ID input divider \ 10 = /4
10391 \ -- \MC Mode Control \ 01 = up to TB0CCR0
10392 \ - \TBCLR TimerB Clear
10395 \ --------------------------------\\
10396 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10397 \ -- \CM Capture Mode
10402 \ --- \OUTMOD \ 011 = set/reset
10408 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
10410 \ ------------------------------\
10411 \ set TimerB to make 50kHz PWM \
10412 \ ------------------------------\
10413 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10414 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
10415 \ ------------------------------\
10416 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10417 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
10418 \ ------------------------------\
10419 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10420 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
10421 \ ------------------------------\
10422 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10423 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
10424 \ ------------------------------\
10425 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10426 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
10427 \ ------------------------------\
10428 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
10429 \ ------------------------------\
10430 \ set TimerB to generate PWM for LCD_Vo
10431 \ ------------------------------\
10432 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
10433 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
10434 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10435 \ ------------------------------\
10436 BIS.B #LCDVo,&LCDVo_DIR \
10437 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
10438 \ ------------------------------\
10439 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10440 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10441 \ ------------------------------\
10442 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10443 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10444 \ ------------------------------\
10445 \ WDT interval init part \
10446 \ ------------------------------\
10447 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
10448 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
10449 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
10450 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
10451 \ ------------------------------\
10453 \ ------------------------------\
10454 BIS.B #RC5,&IR_IE \ enable RC5_Int
10455 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10456 \ ------------------------------\
10457 \ init interrupt vectors
10458 \ ------------------------------\
10459 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
10460 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10461 \ ------------------------------\
10462 \ define LPM mode for ACCEPT \
10463 \ ------------------------------\
10464 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10465 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10466 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10468 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
10470 \ ------------------------------\
10472 \ ------------------------------\
10473 $03E8 20_US \ 1- wait 20 ms
10474 $03 TOP_LCD \ 2- send DB5=DB4=1
10475 $CD 20_US \ 3- wait 4,1 ms
10476 $03 TOP_LCD \ 4- send again DB5=DB4=1
10477 $5 20_US \ 5- wait 0,1 ms
10478 $03 TOP_LCD \ 6- send again again DB5=DB4=1
10479 $2 20_US \ wait 40 us = LCD cycle
10480 $02 TOP_LCD \ 7- send DB5=1 DB4=0
10481 $2 20_US \ wait 40 us = LCD cycle
10482 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10483 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10484 LCD_Clear \ 10- "LCD_Clear"
10485 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10486 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10487 LCD_Clear \ 10- "LCD_Clear"
10488 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10489 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10491 ['] (CR) IS CR \ ' (CR) is CR
10492 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
10494 ." RC5toLCD is running. Type STOP to quit"
10495 \ NOECHO \ uncomment to run this app without terminal connexion
10496 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
10497 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
10501 : STOP \ stops multitasking, must to be used before downloading app
10502 ['] (WARM) IS WARM \ remove START app from FORTH init process
10503 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
10511 CODE MAX \ n1 n2 -- n3 signed maximum
10512 CMP @PSP,TOS \ n2-n1
10513 S< ?GOTO FW1 \ n2<n1
10519 CODE MIN \ n1 n2 -- n3 signed minimum
10520 CMP @PSP,TOS \ n2-n1
10521 S< ?GOTO BW1 \ n2<n1
10527 : U.R \ u n -- display u unsigned in n width (n >= 2)
10529 R> OVER - 0 MAX SPACES TYPE
10533 CODE 20_US \ n -- n * 20 us
10534 BEGIN \ 3 cycles loop + 6~
10535 \ MOV #5,W \ 3 MCLK = 1 MHz
10536 \ MOV #23,W \ 3 MCLK = 4 MHz
10537 MOV #51,W \ 3 MCLK = 8 MHz
10538 \ MOV #104,W \ 3 MCLK = 16 MHz
10539 \ MOV #158,W \ 3 MCLK = 24 MHz
10540 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
10550 CODE TOP_LCD \ LCD Sample
10551 \ \ if write : %xxxxWWWW --
10552 \ \ if read : -- %0000RRRR
10553 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10554 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10555 0= IF \ write LCD bits pattern
10556 AND.B #LCD_DB,TOS \
10557 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10558 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10561 THEN \ read LCD bits pattern
10564 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10565 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10566 AND.B #LCD_DB,TOS \
10571 CODE LCD_W \ byte -- write byte to LCD
10573 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10574 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10575 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10576 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10577 COLON \ high level word starts here
10578 TOP_LCD 2 20_US \ write high nibble first
10583 CODE LCD_WrC \ char -- Write Char
10584 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10589 CODE LCD_WrF \ func -- Write Fonction
10590 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10596 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
10601 $02 LCD_WrF 100 20_us
10605 \ : LCD_Entry_set $04 OR LCD_WrF ;
10607 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
10609 \ : LCD_Display_Shift $10 OR LCD_WrF ;
10611 \ : LCD_Fn_Set $20 OR LCD_WrF ;
10613 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
10615 \ : LCD_Goto $80 OR LCD_WrF ;
10617 \ CODE LCD_R \ -- byte read byte from LCD
10618 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10619 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10620 \ COLON \ starts a FORTH word
10621 \ TOP_LCD 2 20_us \ -- %0000HHHH
10622 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
10623 \ HI2LO \ switch from FORTH to assembler
10624 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
10625 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
10626 \ MOV @RSP+,IP \ restore IP saved by COLON
10631 \ CODE LCD_RdS \ -- status Read Status
10632 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10637 \ CODE LCD_RdC \ -- char Read Char
10638 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10643 \ -------------+------+------+------+------++---+---+---+---+---------+
10644 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
10645 \ -------------+------+------+------+------++---+---+---+---+---------+
10646 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
10647 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
10648 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
10649 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
10650 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
10651 \ -------------+------+------+------+------++---+---+---+---+---------+
10654 \ ******************************\
10655 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10656 \ ******************************\
10657 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
10658 \ ------------------------------\
10659 \ define LPM mode for ACCEPT \
10660 \ ------------------------------\
10661 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10662 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10663 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10664 BIT.B #SW2,&SW2_IN \ test switch S2
10665 0= IF \ case of switch S2 pressed
10666 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
10668 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
10671 BIT.B #SW1,&SW1_IN \ test switch S1 input
10672 0= IF \ case of Switch S1 pressed
10673 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
10675 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
10679 RETI \ CPU is ON, GIE is OFF
10684 \ ------------------------------\
10685 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10686 \ ******************************\
10687 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10688 \ ******************************\
10689 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10690 \ \ SMclock = 8|16|24 MHz
10691 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
10692 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
10693 \ \ SR(9)=new Toggle bit memory (ADD on)
10694 \ ------------------------------\
10695 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
10696 \ ------------------------------\
10697 \ define LPM mode for ACCEPT \
10698 \ ------------------------------\
10699 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10700 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10701 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10702 \ ------------------------------\
10703 \ RC5_FirstStartBitHalfCycle: \
10704 \ ------------------------------\
10705 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
10706 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
10707 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
10708 MOV #1778,X \ RC5_Period in us
10709 MOV #14,W \ count of loop
10711 \ ------------------------------\
10712 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
10713 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
10714 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
10715 \ RC5_Compute_3/4_Period: \ |
10716 RRUM #1,X \ X=1/2 cycle |
10720 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
10721 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
10723 \ ------------------------------\
10724 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
10725 \ ------------------------------\
10726 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10727 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
10728 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10729 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10730 SUB #1,W \ decrement count loop
10731 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
10732 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10733 0<> WHILE \ ----> out of loop ----+
10734 \ RC5_compute_7/4_Time_out: \ |
10735 ADD X,Y \ | out of bound = 7/4 period
10736 \ RC5_WaitHalfCycleP1.2_IFG: \ |
10738 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
10739 0>= IF \ | if cycle time out of bound
10740 BIC #$30,&TA0CTL \ | stop timer_A0
10741 RETI \ | then quit to do nothing
10743 \ ------------------------------\ |
10744 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
10746 MOV &TA0R,X \ | | get new RC5_period value
10747 REPEAT \ ----> loop back --+ |
10748 \ ------------------------------\ |
10749 \ RC5_SampleEndOf: \ <---------------------+
10750 \ ------------------------------\
10751 BIC #$30,&TA0CTL \ stop timer_A0
10752 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
10753 \ ******************************\
10754 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10755 \ ******************************\
10756 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
10757 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
10758 XOR IP,X \ (new XOR old) Toggle bit (13)
10759 BIT #BIT13,X \ X(13) = New_RC5_command
10760 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
10762 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
10763 \ ******************************\
10764 \ RC5_ComputeNewRC5word \
10765 \ ******************************\
10767 MOV &BASE,2(PSP) \ save variable BASE before use
10768 MOV TOS,0(PSP) \ save TOS before use
10769 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
10770 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
10771 \ ******************************\
10772 \ RC5_ComputeC6bit \
10773 \ ******************************\
10774 BIT #$4000,IP \ test /C6 bit in IP
10775 0= IF BIS #$40,TOS \ set C6 bit in S
10776 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
10777 \ ******************************\
10778 \ RC5_CommandByteIsDone \ RC5_code --
10779 \ ******************************\
10781 \ ------------------------------\
10782 \ Display IR_RC5 code \
10783 \ ------------------------------\
10784 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
10785 \ ------------------------------\
10786 LO2HI \ switch from assembler to FORTH
10787 ['] LCD_CLEAR IS CR \ redirects CR
10788 ['] LCD_WrC IS EMIT \ redirects EMIT
10789 $10 BASE ! \ change BASE to hexadecimal
10790 CR ." $" 2 U.R \ print IR_RC5 code
10791 ['] (CR) IS CR \ restore CR
10792 ['] (EMIT) IS EMIT \ restore EMIT
10793 HI2LO \ switch from FORTH to assembler
10794 \ ------------------------------\
10795 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
10796 \ ------------------------------\
10797 MOV @PSP+,&BASE \ restore variable BASE
10798 RETI \ CPU is ON, GIE is OFF
10803 \ ------------------------------\
10804 \ TB0CTL = %0000 0010 1001 0100\$3C0
10805 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10806 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10807 \ -- \ID input divider \ 10 = /4
10808 \ -- \MC Mode Control \ 01 = up to TB0CCR0
10809 \ - \TBCLR TimerB Clear
10812 \ --------------------------------\\
10813 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10814 \ -- \CM Capture Mode
10819 \ --- \OUTMOD \ 011 = set/reset
10825 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
10827 \ ------------------------------\
10828 \ set TimerB to make 50kHz PWM \
10829 \ ------------------------------\
10830 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10831 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
10832 \ ------------------------------\
10833 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
10834 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
10835 \ ------------------------------\
10836 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10837 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
10838 \ ------------------------------\
10839 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10840 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
10841 \ ------------------------------\
10842 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
10843 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
10844 \ ------------------------------\
10845 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
10846 \ ------------------------------\
10847 \ set TimerB to generate PWM for LCD_Vo
10848 \ ------------------------------\
10849 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
10850 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
10851 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10852 \ ------------------------------\
10853 BIS.B #LCDVo,&LCDVo_DIR \
10854 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
10855 \ ------------------------------\
10856 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10857 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10858 \ ------------------------------\
10859 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10860 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10861 \ ------------------------------\
10862 \ WDT interval init part \
10863 \ ------------------------------\
10864 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
10865 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
10866 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
10867 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
10868 \ ------------------------------\
10870 \ ------------------------------\
10871 BIS.B #RC5,&IR_IE \ enable RC5_Int
10872 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10873 \ ------------------------------\
10874 \ init interrupt vectors
10875 \ ------------------------------\
10876 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
10877 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10878 \ ------------------------------\
10879 \ define LPM mode for ACCEPT \
10880 \ ------------------------------\
10881 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10882 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10883 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10885 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
10887 \ ------------------------------\
10889 \ ------------------------------\
10890 $03E8 20_US \ 1- wait 20 ms
10891 $03 TOP_LCD \ 2- send DB5=DB4=1
10892 $CD 20_US \ 3- wait 4,1 ms
10893 $03 TOP_LCD \ 4- send again DB5=DB4=1
10894 $5 20_US \ 5- wait 0,1 ms
10895 $03 TOP_LCD \ 6- send again again DB5=DB4=1
10896 $2 20_US \ wait 40 us = LCD cycle
10897 $02 TOP_LCD \ 7- send DB5=1 DB4=0
10898 $2 20_US \ wait 40 us = LCD cycle
10899 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10900 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10901 LCD_Clear \ 10- "LCD_Clear"
10902 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10903 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10904 LCD_Clear \ 10- "LCD_Clear"
10905 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10906 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10908 ['] (CR) IS CR \ ' (CR) is CR
10909 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
10911 ." RC5toLCD is running. Type STOP to quit"
10912 \ NOECHO \ uncomment to run this app without terminal connexion
10913 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
10914 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
10918 : STOP \ stops multitasking, must to be used before downloading app
10919 ['] (WARM) IS WARM \ remove START app from FORTH init process
10920 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
10928 CODE MAX \ n1 n2 -- n3 signed maximum
10929 CMP @PSP,TOS \ n2-n1
10930 S< ?GOTO FW1 \ n2<n1
10936 CODE MIN \ n1 n2 -- n3 signed minimum
10937 CMP @PSP,TOS \ n2-n1
10938 S< ?GOTO BW1 \ n2<n1
10944 : U.R \ u n -- display u unsigned in n width (n >= 2)
10946 R> OVER - 0 MAX SPACES TYPE
10950 CODE 20_US \ n -- n * 20 us
10951 BEGIN \ 3 cycles loop + 6~
10952 \ MOV #5,W \ 3 MCLK = 1 MHz
10953 \ MOV #23,W \ 3 MCLK = 4 MHz
10954 MOV #51,W \ 3 MCLK = 8 MHz
10955 \ MOV #104,W \ 3 MCLK = 16 MHz
10956 \ MOV #158,W \ 3 MCLK = 24 MHz
10957 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
10967 CODE TOP_LCD \ LCD Sample
10968 \ \ if write : %xxxxWWWW --
10969 \ \ if read : -- %0000RRRR
10970 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10971 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10972 0= IF \ write LCD bits pattern
10973 AND.B #LCD_DB,TOS \
10974 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10975 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10978 THEN \ read LCD bits pattern
10981 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10982 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10983 AND.B #LCD_DB,TOS \
10988 CODE LCD_W \ byte -- write byte to LCD
10990 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
10991 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
10992 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10993 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10994 COLON \ high level word starts here
10995 TOP_LCD 2 20_US \ write high nibble first
11000 CODE LCD_WrC \ char -- Write Char
11001 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11006 CODE LCD_WrF \ func -- Write Fonction
11007 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11013 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
11018 $02 LCD_WrF 100 20_us
11022 \ : LCD_Entry_set $04 OR LCD_WrF ;
11024 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
11026 \ : LCD_Display_Shift $10 OR LCD_WrF ;
11028 \ : LCD_Fn_Set $20 OR LCD_WrF ;
11030 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
11032 \ : LCD_Goto $80 OR LCD_WrF ;
11034 \ CODE LCD_R \ -- byte read byte from LCD
11035 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11036 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11037 \ COLON \ starts a FORTH word
11038 \ TOP_LCD 2 20_us \ -- %0000HHHH
11039 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11040 \ HI2LO \ switch from FORTH to assembler
11041 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11042 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11043 \ MOV @RSP+,IP \ restore IP saved by COLON
11048 \ CODE LCD_RdS \ -- status Read Status
11049 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11054 \ CODE LCD_RdC \ -- char Read Char
11055 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11060 \ -------------+------+------+------+------++---+---+---+---+---------+
11061 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
11062 \ -------------+------+------+------+------++---+---+---+---+---------+
11063 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
11064 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
11065 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
11066 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
11067 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
11068 \ -------------+------+------+------+------++---+---+---+---+---------+
11071 \ ******************************\
11072 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11073 \ ******************************\
11074 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
11075 \ ------------------------------\
11076 \ define LPM mode for ACCEPT \
11077 \ ------------------------------\
11078 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11079 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11080 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11081 BIT.B #SW2,&SW2_IN \ test switch S2
11082 0= IF \ case of switch S2 pressed
11083 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
11085 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
11088 BIT.B #SW1,&SW1_IN \ test switch S1 input
11089 0= IF \ case of Switch S1 pressed
11090 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
11092 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
11096 RETI \ CPU is ON, GIE is OFF
11101 \ ------------------------------\
11102 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11103 \ ******************************\
11104 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11105 \ ******************************\
11106 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11107 \ \ SMclock = 8|16|24 MHz
11108 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
11109 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
11110 \ \ SR(9)=new Toggle bit memory (ADD on)
11111 \ ------------------------------\
11112 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
11113 \ ------------------------------\
11114 \ define LPM mode for ACCEPT \
11115 \ ------------------------------\
11116 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11117 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11118 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11119 \ ------------------------------\
11120 \ RC5_FirstStartBitHalfCycle: \
11121 \ ------------------------------\
11122 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
11123 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
11124 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
11125 MOV #1778,X \ RC5_Period in us
11126 MOV #14,W \ count of loop
11128 \ ------------------------------\
11129 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
11130 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
11131 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
11132 \ RC5_Compute_3/4_Period: \ |
11133 RRUM #1,X \ X=1/2 cycle |
11137 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
11138 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
11140 \ ------------------------------\
11141 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
11142 \ ------------------------------\
11143 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11144 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
11145 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11146 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11147 SUB #1,W \ decrement count loop
11148 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
11149 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11150 0<> WHILE \ ----> out of loop ----+
11151 \ RC5_compute_7/4_Time_out: \ |
11152 ADD X,Y \ | out of bound = 7/4 period
11153 \ RC5_WaitHalfCycleP1.2_IFG: \ |
11155 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
11156 0>= IF \ | if cycle time out of bound
11157 BIC #$30,&TA0CTL \ | stop timer_A0
11158 RETI \ | then quit to do nothing
11160 \ ------------------------------\ |
11161 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
11163 MOV &TA0R,X \ | | get new RC5_period value
11164 REPEAT \ ----> loop back --+ |
11165 \ ------------------------------\ |
11166 \ RC5_SampleEndOf: \ <---------------------+
11167 \ ------------------------------\
11168 BIC #$30,&TA0CTL \ stop timer_A0
11169 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
11170 \ ******************************\
11171 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11172 \ ******************************\
11173 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
11174 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
11175 XOR IP,X \ (new XOR old) Toggle bit (13)
11176 BIT #BIT13,X \ X(13) = New_RC5_command
11177 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
11179 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
11180 \ ******************************\
11181 \ RC5_ComputeNewRC5word \
11182 \ ******************************\
11184 MOV &BASE,2(PSP) \ save variable BASE before use
11185 MOV TOS,0(PSP) \ save TOS before use
11186 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
11187 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
11188 \ ******************************\
11189 \ RC5_ComputeC6bit \
11190 \ ******************************\
11191 BIT #$4000,IP \ test /C6 bit in IP
11192 0= IF BIS #$40,TOS \ set C6 bit in S
11193 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
11194 \ ******************************\
11195 \ RC5_CommandByteIsDone \ RC5_code --
11196 \ ******************************\
11198 \ ------------------------------\
11199 \ Display IR_RC5 code \
11200 \ ------------------------------\
11201 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
11202 \ ------------------------------\
11203 LO2HI \ switch from assembler to FORTH
11204 ['] LCD_CLEAR IS CR \ redirects CR
11205 ['] LCD_WrC IS EMIT \ redirects EMIT
11206 $10 BASE ! \ change BASE to hexadecimal
11207 CR ." $" 2 U.R \ print IR_RC5 code
11208 ['] (CR) IS CR \ restore CR
11209 ['] (EMIT) IS EMIT \ restore EMIT
11210 HI2LO \ switch from FORTH to assembler
11211 \ ------------------------------\
11212 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
11213 \ ------------------------------\
11214 MOV @PSP+,&BASE \ restore variable BASE
11215 RETI \ CPU is ON, GIE is OFF
11220 \ ------------------------------\
11221 \ TB0CTL = %0000 0010 1001 0100\$3C0
11222 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11223 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11224 \ -- \ID input divider \ 10 = /4
11225 \ -- \MC Mode Control \ 01 = up to TB0CCR0
11226 \ - \TBCLR TimerB Clear
11229 \ --------------------------------\\
11230 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11231 \ -- \CM Capture Mode
11236 \ --- \OUTMOD \ 011 = set/reset
11242 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
11244 \ ------------------------------\
11245 \ set TimerB to make 50kHz PWM \
11246 \ ------------------------------\
11247 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11248 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
11249 \ ------------------------------\
11250 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11251 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
11252 \ ------------------------------\
11253 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11254 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
11255 \ ------------------------------\
11256 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11257 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
11258 \ ------------------------------\
11259 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11260 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
11261 \ ------------------------------\
11262 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
11263 \ ------------------------------\
11264 \ set TimerB to generate PWM for LCD_Vo
11265 \ ------------------------------\
11266 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
11267 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
11268 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11269 \ ------------------------------\
11270 BIS.B #LCDVo,&LCDVo_DIR \
11271 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
11272 \ ------------------------------\
11273 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11274 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11275 \ ------------------------------\
11276 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11277 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11278 \ ------------------------------\
11279 \ WDT interval init part \
11280 \ ------------------------------\
11281 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
11282 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
11283 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
11284 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
11285 \ ------------------------------\
11287 \ ------------------------------\
11288 BIS.B #RC5,&IR_IE \ enable RC5_Int
11289 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11290 \ ------------------------------\
11291 \ init interrupt vectors
11292 \ ------------------------------\
11293 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
11294 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11295 \ ------------------------------\
11296 \ define LPM mode for ACCEPT \
11297 \ ------------------------------\
11298 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11299 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11300 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11302 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
11304 \ ------------------------------\
11306 \ ------------------------------\
11307 $03E8 20_US \ 1- wait 20 ms
11308 $03 TOP_LCD \ 2- send DB5=DB4=1
11309 $CD 20_US \ 3- wait 4,1 ms
11310 $03 TOP_LCD \ 4- send again DB5=DB4=1
11311 $5 20_US \ 5- wait 0,1 ms
11312 $03 TOP_LCD \ 6- send again again DB5=DB4=1
11313 $2 20_US \ wait 40 us = LCD cycle
11314 $02 TOP_LCD \ 7- send DB5=1 DB4=0
11315 $2 20_US \ wait 40 us = LCD cycle
11316 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11317 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11318 LCD_Clear \ 10- "LCD_Clear"
11319 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11320 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11321 LCD_Clear \ 10- "LCD_Clear"
11322 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11323 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11325 ['] (CR) IS CR \ ' (CR) is CR
11326 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
11328 ." RC5toLCD is running. Type STOP to quit"
11329 \ NOECHO \ uncomment to run this app without terminal connexion
11330 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
11331 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
11335 : STOP \ stops multitasking, must to be used before downloading app
11336 ['] (WARM) IS WARM \ remove START app from FORTH init process
11337 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
11345 CODE MAX \ n1 n2 -- n3 signed maximum
11346 CMP @PSP,TOS \ n2-n1
11347 S< ?GOTO FW1 \ n2<n1
11353 CODE MIN \ n1 n2 -- n3 signed minimum
11354 CMP @PSP,TOS \ n2-n1
11355 S< ?GOTO BW1 \ n2<n1
11361 : U.R \ u n -- display u unsigned in n width (n >= 2)
11363 R> OVER - 0 MAX SPACES TYPE
11367 CODE 20_US \ n -- n * 20 us
11368 BEGIN \ 3 cycles loop + 6~
11369 \ MOV #5,W \ 3 MCLK = 1 MHz
11370 \ MOV #23,W \ 3 MCLK = 4 MHz
11371 MOV #51,W \ 3 MCLK = 8 MHz
11372 \ MOV #104,W \ 3 MCLK = 16 MHz
11373 \ MOV #158,W \ 3 MCLK = 24 MHz
11374 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
11384 CODE TOP_LCD \ LCD Sample
11385 \ \ if write : %xxxxWWWW --
11386 \ \ if read : -- %0000RRRR
11387 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11388 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11389 0= IF \ write LCD bits pattern
11390 AND.B #LCD_DB,TOS \
11391 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11392 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11395 THEN \ read LCD bits pattern
11398 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11399 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11400 AND.B #LCD_DB,TOS \
11405 CODE LCD_W \ byte -- write byte to LCD
11407 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11408 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11409 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11410 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11411 COLON \ high level word starts here
11412 TOP_LCD 2 20_US \ write high nibble first
11417 CODE LCD_WrC \ char -- Write Char
11418 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11423 CODE LCD_WrF \ func -- Write Fonction
11424 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11430 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
11435 $02 LCD_WrF 100 20_us
11439 \ : LCD_Entry_set $04 OR LCD_WrF ;
11441 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
11443 \ : LCD_Display_Shift $10 OR LCD_WrF ;
11445 \ : LCD_Fn_Set $20 OR LCD_WrF ;
11447 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
11449 \ : LCD_Goto $80 OR LCD_WrF ;
11451 \ CODE LCD_R \ -- byte read byte from LCD
11452 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11453 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11454 \ COLON \ starts a FORTH word
11455 \ TOP_LCD 2 20_us \ -- %0000HHHH
11456 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11457 \ HI2LO \ switch from FORTH to assembler
11458 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11459 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11460 \ MOV @RSP+,IP \ restore IP saved by COLON
11465 \ CODE LCD_RdS \ -- status Read Status
11466 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11471 \ CODE LCD_RdC \ -- char Read Char
11472 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11477 \ -------------+------+------+------+------++---+---+---+---+---------+
11478 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
11479 \ -------------+------+------+------+------++---+---+---+---+---------+
11480 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
11481 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
11482 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
11483 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
11484 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
11485 \ -------------+------+------+------+------++---+---+---+---+---------+
11488 \ ******************************\
11489 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11490 \ ******************************\
11491 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
11492 \ ------------------------------\
11493 \ define LPM mode for ACCEPT \
11494 \ ------------------------------\
11495 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11496 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11497 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11498 BIT.B #SW2,&SW2_IN \ test switch S2
11499 0= IF \ case of switch S2 pressed
11500 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
11502 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
11505 BIT.B #SW1,&SW1_IN \ test switch S1 input
11506 0= IF \ case of Switch S1 pressed
11507 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
11509 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
11513 RETI \ CPU is ON, GIE is OFF
11518 \ ------------------------------\
11519 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11520 \ ******************************\
11521 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11522 \ ******************************\
11523 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11524 \ \ SMclock = 8|16|24 MHz
11525 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
11526 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
11527 \ \ SR(9)=new Toggle bit memory (ADD on)
11528 \ ------------------------------\
11529 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
11530 \ ------------------------------\
11531 \ define LPM mode for ACCEPT \
11532 \ ------------------------------\
11533 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11534 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11535 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11536 \ ------------------------------\
11537 \ RC5_FirstStartBitHalfCycle: \
11538 \ ------------------------------\
11539 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
11540 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
11541 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
11542 MOV #1778,X \ RC5_Period in us
11543 MOV #14,W \ count of loop
11545 \ ------------------------------\
11546 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
11547 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
11548 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
11549 \ RC5_Compute_3/4_Period: \ |
11550 RRUM #1,X \ X=1/2 cycle |
11554 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
11555 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
11557 \ ------------------------------\
11558 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
11559 \ ------------------------------\
11560 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11561 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
11562 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11563 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11564 SUB #1,W \ decrement count loop
11565 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
11566 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11567 0<> WHILE \ ----> out of loop ----+
11568 \ RC5_compute_7/4_Time_out: \ |
11569 ADD X,Y \ | out of bound = 7/4 period
11570 \ RC5_WaitHalfCycleP1.2_IFG: \ |
11572 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
11573 0>= IF \ | if cycle time out of bound
11574 BIC #$30,&TA0CTL \ | stop timer_A0
11575 RETI \ | then quit to do nothing
11577 \ ------------------------------\ |
11578 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
11580 MOV &TA0R,X \ | | get new RC5_period value
11581 REPEAT \ ----> loop back --+ |
11582 \ ------------------------------\ |
11583 \ RC5_SampleEndOf: \ <---------------------+
11584 \ ------------------------------\
11585 BIC #$30,&TA0CTL \ stop timer_A0
11586 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
11587 \ ******************************\
11588 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11589 \ ******************************\
11590 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
11591 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
11592 XOR IP,X \ (new XOR old) Toggle bit (13)
11593 BIT #BIT13,X \ X(13) = New_RC5_command
11594 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
11596 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
11597 \ ******************************\
11598 \ RC5_ComputeNewRC5word \
11599 \ ******************************\
11601 MOV &BASE,2(PSP) \ save variable BASE before use
11602 MOV TOS,0(PSP) \ save TOS before use
11603 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
11604 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
11605 \ ******************************\
11606 \ RC5_ComputeC6bit \
11607 \ ******************************\
11608 BIT #$4000,IP \ test /C6 bit in IP
11609 0= IF BIS #$40,TOS \ set C6 bit in S
11610 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
11611 \ ******************************\
11612 \ RC5_CommandByteIsDone \ RC5_code --
11613 \ ******************************\
11615 \ ------------------------------\
11616 \ Display IR_RC5 code \
11617 \ ------------------------------\
11618 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
11619 \ ------------------------------\
11620 LO2HI \ switch from assembler to FORTH
11621 ['] LCD_CLEAR IS CR \ redirects CR
11622 ['] LCD_WrC IS EMIT \ redirects EMIT
11623 $10 BASE ! \ change BASE to hexadecimal
11624 CR ." $" 2 U.R \ print IR_RC5 code
11625 ['] (CR) IS CR \ restore CR
11626 ['] (EMIT) IS EMIT \ restore EMIT
11627 HI2LO \ switch from FORTH to assembler
11628 \ ------------------------------\
11629 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
11630 \ ------------------------------\
11631 MOV @PSP+,&BASE \ restore variable BASE
11632 RETI \ CPU is ON, GIE is OFF
11637 \ ------------------------------\
11638 \ TB0CTL = %0000 0010 1001 0100\$3C0
11639 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11640 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11641 \ -- \ID input divider \ 10 = /4
11642 \ -- \MC Mode Control \ 01 = up to TB0CCR0
11643 \ - \TBCLR TimerB Clear
11646 \ --------------------------------\\
11647 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11648 \ -- \CM Capture Mode
11653 \ --- \OUTMOD \ 011 = set/reset
11659 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
11661 \ ------------------------------\
11662 \ set TimerB to make 50kHz PWM \
11663 \ ------------------------------\
11664 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11665 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
11666 \ ------------------------------\
11667 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
11668 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
11669 \ ------------------------------\
11670 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11671 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
11672 \ ------------------------------\
11673 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11674 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
11675 \ ------------------------------\
11676 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
11677 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
11678 \ ------------------------------\
11679 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
11680 \ ------------------------------\
11681 \ set TimerB to generate PWM for LCD_Vo
11682 \ ------------------------------\
11683 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
11684 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
11685 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11686 \ ------------------------------\
11687 BIS.B #LCDVo,&LCDVo_DIR \
11688 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
11689 \ ------------------------------\
11690 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11691 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11692 \ ------------------------------\
11693 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11694 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11695 \ ------------------------------\
11696 \ WDT interval init part \
11697 \ ------------------------------\
11698 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
11699 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
11700 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
11701 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
11702 \ ------------------------------\
11704 \ ------------------------------\
11705 BIS.B #RC5,&IR_IE \ enable RC5_Int
11706 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11707 \ ------------------------------\
11708 \ init interrupt vectors
11709 \ ------------------------------\
11710 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
11711 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11712 \ ------------------------------\
11713 \ define LPM mode for ACCEPT \
11714 \ ------------------------------\
11715 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11716 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11717 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11719 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
11721 \ ------------------------------\
11723 \ ------------------------------\
11724 $03E8 20_US \ 1- wait 20 ms
11725 $03 TOP_LCD \ 2- send DB5=DB4=1
11726 $CD 20_US \ 3- wait 4,1 ms
11727 $03 TOP_LCD \ 4- send again DB5=DB4=1
11728 $5 20_US \ 5- wait 0,1 ms
11729 $03 TOP_LCD \ 6- send again again DB5=DB4=1
11730 $2 20_US \ wait 40 us = LCD cycle
11731 $02 TOP_LCD \ 7- send DB5=1 DB4=0
11732 $2 20_US \ wait 40 us = LCD cycle
11733 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11734 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11735 LCD_Clear \ 10- "LCD_Clear"
11736 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11737 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11738 LCD_Clear \ 10- "LCD_Clear"
11739 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11740 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11742 ['] (CR) IS CR \ ' (CR) is CR
11743 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
11745 ." RC5toLCD is running. Type STOP to quit"
11746 \ NOECHO \ uncomment to run this app without terminal connexion
11747 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
11748 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
11752 : STOP \ stops multitasking, must to be used before downloading app
11753 ['] (WARM) IS WARM \ remove START app from FORTH init process
11754 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
11762 CODE MAX \ n1 n2 -- n3 signed maximum
11763 CMP @PSP,TOS \ n2-n1
11764 S< ?GOTO FW1 \ n2<n1
11770 CODE MIN \ n1 n2 -- n3 signed minimum
11771 CMP @PSP,TOS \ n2-n1
11772 S< ?GOTO BW1 \ n2<n1
11778 : U.R \ u n -- display u unsigned in n width (n >= 2)
11780 R> OVER - 0 MAX SPACES TYPE
11784 CODE 20_US \ n -- n * 20 us
11785 BEGIN \ 3 cycles loop + 6~
11786 \ MOV #5,W \ 3 MCLK = 1 MHz
11787 \ MOV #23,W \ 3 MCLK = 4 MHz
11788 MOV #51,W \ 3 MCLK = 8 MHz
11789 \ MOV #104,W \ 3 MCLK = 16 MHz
11790 \ MOV #158,W \ 3 MCLK = 24 MHz
11791 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
11801 CODE TOP_LCD \ LCD Sample
11802 \ \ if write : %xxxxWWWW --
11803 \ \ if read : -- %0000RRRR
11804 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11805 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11806 0= IF \ write LCD bits pattern
11807 AND.B #LCD_DB,TOS \
11808 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11809 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11812 THEN \ read LCD bits pattern
11815 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11816 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11817 AND.B #LCD_DB,TOS \
11822 CODE LCD_W \ byte -- write byte to LCD
11824 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
11825 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
11826 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11827 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11828 COLON \ high level word starts here
11829 TOP_LCD 2 20_US \ write high nibble first
11834 CODE LCD_WrC \ char -- Write Char
11835 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11840 CODE LCD_WrF \ func -- Write Fonction
11841 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11847 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
11852 $02 LCD_WrF 100 20_us
11856 \ : LCD_Entry_set $04 OR LCD_WrF ;
11858 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
11860 \ : LCD_Display_Shift $10 OR LCD_WrF ;
11862 \ : LCD_Fn_Set $20 OR LCD_WrF ;
11864 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
11866 \ : LCD_Goto $80 OR LCD_WrF ;
11868 \ CODE LCD_R \ -- byte read byte from LCD
11869 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11870 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11871 \ COLON \ starts a FORTH word
11872 \ TOP_LCD 2 20_us \ -- %0000HHHH
11873 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
11874 \ HI2LO \ switch from FORTH to assembler
11875 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
11876 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
11877 \ MOV @RSP+,IP \ restore IP saved by COLON
11882 \ CODE LCD_RdS \ -- status Read Status
11883 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11888 \ CODE LCD_RdC \ -- char Read Char
11889 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11894 \ -------------+------+------+------+------++---+---+---+---+---------+
11895 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
11896 \ -------------+------+------+------+------++---+---+---+---+---------+
11897 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
11898 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
11899 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
11900 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
11901 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
11902 \ -------------+------+------+------+------++---+---+---+---+---------+
11905 \ ******************************\
11906 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11907 \ ******************************\
11908 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
11909 \ ------------------------------\
11910 \ define LPM mode for ACCEPT \
11911 \ ------------------------------\
11912 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11913 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11914 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11915 BIT.B #SW2,&SW2_IN \ test switch S2
11916 0= IF \ case of switch S2 pressed
11917 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
11919 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
11922 BIT.B #SW1,&SW1_IN \ test switch S1 input
11923 0= IF \ case of Switch S1 pressed
11924 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
11926 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
11930 RETI \ CPU is ON, GIE is OFF
11935 \ ------------------------------\
11936 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11937 \ ******************************\
11938 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11939 \ ******************************\
11940 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11941 \ \ SMclock = 8|16|24 MHz
11942 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
11943 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
11944 \ \ SR(9)=new Toggle bit memory (ADD on)
11945 \ ------------------------------\
11946 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
11947 \ ------------------------------\
11948 \ define LPM mode for ACCEPT \
11949 \ ------------------------------\
11950 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11951 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11952 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11953 \ ------------------------------\
11954 \ RC5_FirstStartBitHalfCycle: \
11955 \ ------------------------------\
11956 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
11957 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
11958 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
11959 MOV #1778,X \ RC5_Period in us
11960 MOV #14,W \ count of loop
11962 \ ------------------------------\
11963 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
11964 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
11965 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
11966 \ RC5_Compute_3/4_Period: \ |
11967 RRUM #1,X \ X=1/2 cycle |
11971 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
11972 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
11974 \ ------------------------------\
11975 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
11976 \ ------------------------------\
11977 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11978 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
11979 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11980 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11981 SUB #1,W \ decrement count loop
11982 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
11983 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11984 0<> WHILE \ ----> out of loop ----+
11985 \ RC5_compute_7/4_Time_out: \ |
11986 ADD X,Y \ | out of bound = 7/4 period
11987 \ RC5_WaitHalfCycleP1.2_IFG: \ |
11989 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
11990 0>= IF \ | if cycle time out of bound
11991 BIC #$30,&TA0CTL \ | stop timer_A0
11992 RETI \ | then quit to do nothing
11994 \ ------------------------------\ |
11995 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
11997 MOV &TA0R,X \ | | get new RC5_period value
11998 REPEAT \ ----> loop back --+ |
11999 \ ------------------------------\ |
12000 \ RC5_SampleEndOf: \ <---------------------+
12001 \ ------------------------------\
12002 BIC #$30,&TA0CTL \ stop timer_A0
12003 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
12004 \ ******************************\
12005 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12006 \ ******************************\
12007 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
12008 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
12009 XOR IP,X \ (new XOR old) Toggle bit (13)
12010 BIT #BIT13,X \ X(13) = New_RC5_command
12011 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
12013 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
12014 \ ******************************\
12015 \ RC5_ComputeNewRC5word \
12016 \ ******************************\
12018 MOV &BASE,2(PSP) \ save variable BASE before use
12019 MOV TOS,0(PSP) \ save TOS before use
12020 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
12021 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
12022 \ ******************************\
12023 \ RC5_ComputeC6bit \
12024 \ ******************************\
12025 BIT #$4000,IP \ test /C6 bit in IP
12026 0= IF BIS #$40,TOS \ set C6 bit in S
12027 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
12028 \ ******************************\
12029 \ RC5_CommandByteIsDone \ RC5_code --
12030 \ ******************************\
12032 \ ------------------------------\
12033 \ Display IR_RC5 code \
12034 \ ------------------------------\
12035 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
12036 \ ------------------------------\
12037 LO2HI \ switch from assembler to FORTH
12038 ['] LCD_CLEAR IS CR \ redirects CR
12039 ['] LCD_WrC IS EMIT \ redirects EMIT
12040 $10 BASE ! \ change BASE to hexadecimal
12041 CR ." $" 2 U.R \ print IR_RC5 code
12042 ['] (CR) IS CR \ restore CR
12043 ['] (EMIT) IS EMIT \ restore EMIT
12044 HI2LO \ switch from FORTH to assembler
12045 \ ------------------------------\
12046 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
12047 \ ------------------------------\
12048 MOV @PSP+,&BASE \ restore variable BASE
12049 RETI \ CPU is ON, GIE is OFF
12054 \ ------------------------------\
12055 \ TB0CTL = %0000 0010 1001 0100\$3C0
12056 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12057 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12058 \ -- \ID input divider \ 10 = /4
12059 \ -- \MC Mode Control \ 01 = up to TB0CCR0
12060 \ - \TBCLR TimerB Clear
12063 \ --------------------------------\\
12064 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12065 \ -- \CM Capture Mode
12070 \ --- \OUTMOD \ 011 = set/reset
12076 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
12078 \ ------------------------------\
12079 \ set TimerB to make 50kHz PWM \
12080 \ ------------------------------\
12081 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12082 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
12083 \ ------------------------------\
12084 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12085 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
12086 \ ------------------------------\
12087 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12088 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
12089 \ ------------------------------\
12090 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12091 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
12092 \ ------------------------------\
12093 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12094 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
12095 \ ------------------------------\
12096 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
12097 \ ------------------------------\
12098 \ set TimerB to generate PWM for LCD_Vo
12099 \ ------------------------------\
12100 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
12101 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
12102 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12103 \ ------------------------------\
12104 BIS.B #LCDVo,&LCDVo_DIR \
12105 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
12106 \ ------------------------------\
12107 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12108 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12109 \ ------------------------------\
12110 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12111 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12112 \ ------------------------------\
12113 \ WDT interval init part \
12114 \ ------------------------------\
12115 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
12116 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
12117 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
12118 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
12119 \ ------------------------------\
12121 \ ------------------------------\
12122 BIS.B #RC5,&IR_IE \ enable RC5_Int
12123 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12124 \ ------------------------------\
12125 \ init interrupt vectors
12126 \ ------------------------------\
12127 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
12128 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12129 \ ------------------------------\
12130 \ define LPM mode for ACCEPT \
12131 \ ------------------------------\
12132 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12133 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12134 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12136 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
12138 \ ------------------------------\
12140 \ ------------------------------\
12141 $03E8 20_US \ 1- wait 20 ms
12142 $03 TOP_LCD \ 2- send DB5=DB4=1
12143 $CD 20_US \ 3- wait 4,1 ms
12144 $03 TOP_LCD \ 4- send again DB5=DB4=1
12145 $5 20_US \ 5- wait 0,1 ms
12146 $03 TOP_LCD \ 6- send again again DB5=DB4=1
12147 $2 20_US \ wait 40 us = LCD cycle
12148 $02 TOP_LCD \ 7- send DB5=1 DB4=0
12149 $2 20_US \ wait 40 us = LCD cycle
12150 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12151 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12152 LCD_Clear \ 10- "LCD_Clear"
12153 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12154 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12155 LCD_Clear \ 10- "LCD_Clear"
12156 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12157 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12159 ['] (CR) IS CR \ ' (CR) is CR
12160 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
12162 ." RC5toLCD is running. Type STOP to quit"
12163 \ NOECHO \ uncomment to run this app without terminal connexion
12164 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
12165 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
12169 : STOP \ stops multitasking, must to be used before downloading app
12170 ['] (WARM) IS WARM \ remove START app from FORTH init process
12171 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
12179 CODE MAX \ n1 n2 -- n3 signed maximum
12180 CMP @PSP,TOS \ n2-n1
12181 S< ?GOTO FW1 \ n2<n1
12187 CODE MIN \ n1 n2 -- n3 signed minimum
12188 CMP @PSP,TOS \ n2-n1
12189 S< ?GOTO BW1 \ n2<n1
12195 : U.R \ u n -- display u unsigned in n width (n >= 2)
12197 R> OVER - 0 MAX SPACES TYPE
12201 CODE 20_US \ n -- n * 20 us
12202 BEGIN \ 3 cycles loop + 6~
12203 \ MOV #5,W \ 3 MCLK = 1 MHz
12204 \ MOV #23,W \ 3 MCLK = 4 MHz
12205 MOV #51,W \ 3 MCLK = 8 MHz
12206 \ MOV #104,W \ 3 MCLK = 16 MHz
12207 \ MOV #158,W \ 3 MCLK = 24 MHz
12208 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
12218 CODE TOP_LCD \ LCD Sample
12219 \ \ if write : %xxxxWWWW --
12220 \ \ if read : -- %0000RRRR
12221 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12222 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12223 0= IF \ write LCD bits pattern
12224 AND.B #LCD_DB,TOS \
12225 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12226 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12229 THEN \ read LCD bits pattern
12232 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12233 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12234 AND.B #LCD_DB,TOS \
12239 CODE LCD_W \ byte -- write byte to LCD
12241 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
12242 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
12243 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12244 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12245 COLON \ high level word starts here
12246 TOP_LCD 2 20_US \ write high nibble first
12251 CODE LCD_WrC \ char -- Write Char
12252 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12257 CODE LCD_WrF \ func -- Write Fonction
12258 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12264 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
12269 $02 LCD_WrF 100 20_us
12273 \ : LCD_Entry_set $04 OR LCD_WrF ;
12275 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
12277 \ : LCD_Display_Shift $10 OR LCD_WrF ;
12279 \ : LCD_Fn_Set $20 OR LCD_WrF ;
12281 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
12283 \ : LCD_Goto $80 OR LCD_WrF ;
12285 \ CODE LCD_R \ -- byte read byte from LCD
12286 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12287 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12288 \ COLON \ starts a FORTH word
12289 \ TOP_LCD 2 20_us \ -- %0000HHHH
12290 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
12291 \ HI2LO \ switch from FORTH to assembler
12292 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
12293 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
12294 \ MOV @RSP+,IP \ restore IP saved by COLON
12299 \ CODE LCD_RdS \ -- status Read Status
12300 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12305 \ CODE LCD_RdC \ -- char Read Char
12306 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12311 \ -------------+------+------+------+------++---+---+---+---+---------+
12312 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
12313 \ -------------+------+------+------+------++---+---+---+---+---------+
12314 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
12315 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
12316 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
12317 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
12318 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
12319 \ -------------+------+------+------+------++---+---+---+---+---------+
12322 \ ******************************\
12323 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12324 \ ******************************\
12325 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
12326 \ ------------------------------\
12327 \ define LPM mode for ACCEPT \
12328 \ ------------------------------\
12329 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12330 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12331 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12332 BIT.B #SW2,&SW2_IN \ test switch S2
12333 0= IF \ case of switch S2 pressed
12334 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
12336 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
12339 BIT.B #SW1,&SW1_IN \ test switch S1 input
12340 0= IF \ case of Switch S1 pressed
12341 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
12343 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
12347 RETI \ CPU is ON, GIE is OFF
12352 \ ------------------------------\
12353 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12354 \ ******************************\
12355 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12356 \ ******************************\
12357 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12358 \ \ SMclock = 8|16|24 MHz
12359 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
12360 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
12361 \ \ SR(9)=new Toggle bit memory (ADD on)
12362 \ ------------------------------\
12363 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
12364 \ ------------------------------\
12365 \ define LPM mode for ACCEPT \
12366 \ ------------------------------\
12367 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12368 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12369 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12370 \ ------------------------------\
12371 \ RC5_FirstStartBitHalfCycle: \
12372 \ ------------------------------\
12373 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
12374 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
12375 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
12376 MOV #1778,X \ RC5_Period in us
12377 MOV #14,W \ count of loop
12379 \ ------------------------------\
12380 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
12381 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
12382 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
12383 \ RC5_Compute_3/4_Period: \ |
12384 RRUM #1,X \ X=1/2 cycle |
12388 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
12389 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
12391 \ ------------------------------\
12392 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
12393 \ ------------------------------\
12394 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12395 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
12396 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12397 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12398 SUB #1,W \ decrement count loop
12399 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
12400 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12401 0<> WHILE \ ----> out of loop ----+
12402 \ RC5_compute_7/4_Time_out: \ |
12403 ADD X,Y \ | out of bound = 7/4 period
12404 \ RC5_WaitHalfCycleP1.2_IFG: \ |
12406 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
12407 0>= IF \ | if cycle time out of bound
12408 BIC #$30,&TA0CTL \ | stop timer_A0
12409 RETI \ | then quit to do nothing
12411 \ ------------------------------\ |
12412 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
12414 MOV &TA0R,X \ | | get new RC5_period value
12415 REPEAT \ ----> loop back --+ |
12416 \ ------------------------------\ |
12417 \ RC5_SampleEndOf: \ <---------------------+
12418 \ ------------------------------\
12419 BIC #$30,&TA0CTL \ stop timer_A0
12420 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
12421 \ ******************************\
12422 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12423 \ ******************************\
12424 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
12425 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
12426 XOR IP,X \ (new XOR old) Toggle bit (13)
12427 BIT #BIT13,X \ X(13) = New_RC5_command
12428 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
12430 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
12431 \ ******************************\
12432 \ RC5_ComputeNewRC5word \
12433 \ ******************************\
12435 MOV &BASE,2(PSP) \ save variable BASE before use
12436 MOV TOS,0(PSP) \ save TOS before use
12437 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
12438 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
12439 \ ******************************\
12440 \ RC5_ComputeC6bit \
12441 \ ******************************\
12442 BIT #$4000,IP \ test /C6 bit in IP
12443 0= IF BIS #$40,TOS \ set C6 bit in S
12444 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
12445 \ ******************************\
12446 \ RC5_CommandByteIsDone \ RC5_code --
12447 \ ******************************\
12449 \ ------------------------------\
12450 \ Display IR_RC5 code \
12451 \ ------------------------------\
12452 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
12453 \ ------------------------------\
12454 LO2HI \ switch from assembler to FORTH
12455 ['] LCD_CLEAR IS CR \ redirects CR
12456 ['] LCD_WrC IS EMIT \ redirects EMIT
12457 $10 BASE ! \ change BASE to hexadecimal
12458 CR ." $" 2 U.R \ print IR_RC5 code
12459 ['] (CR) IS CR \ restore CR
12460 ['] (EMIT) IS EMIT \ restore EMIT
12461 HI2LO \ switch from FORTH to assembler
12462 \ ------------------------------\
12463 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
12464 \ ------------------------------\
12465 MOV @PSP+,&BASE \ restore variable BASE
12466 RETI \ CPU is ON, GIE is OFF
12471 \ ------------------------------\
12472 \ TB0CTL = %0000 0010 1001 0100\$3C0
12473 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12474 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12475 \ -- \ID input divider \ 10 = /4
12476 \ -- \MC Mode Control \ 01 = up to TB0CCR0
12477 \ - \TBCLR TimerB Clear
12480 \ --------------------------------\\
12481 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12482 \ -- \CM Capture Mode
12487 \ --- \OUTMOD \ 011 = set/reset
12493 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
12495 \ ------------------------------\
12496 \ set TimerB to make 50kHz PWM \
12497 \ ------------------------------\
12498 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12499 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
12500 \ ------------------------------\
12501 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12502 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
12503 \ ------------------------------\
12504 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12505 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
12506 \ ------------------------------\
12507 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12508 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
12509 \ ------------------------------\
12510 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12511 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
12512 \ ------------------------------\
12513 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
12514 \ ------------------------------\
12515 \ set TimerB to generate PWM for LCD_Vo
12516 \ ------------------------------\
12517 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
12518 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
12519 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12520 \ ------------------------------\
12521 BIS.B #LCDVo,&LCDVo_DIR \
12522 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
12523 \ ------------------------------\
12524 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12525 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12526 \ ------------------------------\
12527 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12528 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12529 \ ------------------------------\
12530 \ WDT interval init part \
12531 \ ------------------------------\
12532 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
12533 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
12534 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
12535 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
12536 \ ------------------------------\
12538 \ ------------------------------\
12539 BIS.B #RC5,&IR_IE \ enable RC5_Int
12540 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12541 \ ------------------------------\
12542 \ init interrupt vectors
12543 \ ------------------------------\
12544 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
12545 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12546 \ ------------------------------\
12547 \ define LPM mode for ACCEPT \
12548 \ ------------------------------\
12549 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12550 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12551 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12553 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
12555 \ ------------------------------\
12557 \ ------------------------------\
12558 $03E8 20_US \ 1- wait 20 ms
12559 $03 TOP_LCD \ 2- send DB5=DB4=1
12560 $CD 20_US \ 3- wait 4,1 ms
12561 $03 TOP_LCD \ 4- send again DB5=DB4=1
12562 $5 20_US \ 5- wait 0,1 ms
12563 $03 TOP_LCD \ 6- send again again DB5=DB4=1
12564 $2 20_US \ wait 40 us = LCD cycle
12565 $02 TOP_LCD \ 7- send DB5=1 DB4=0
12566 $2 20_US \ wait 40 us = LCD cycle
12567 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12568 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12569 LCD_Clear \ 10- "LCD_Clear"
12570 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12571 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12572 LCD_Clear \ 10- "LCD_Clear"
12573 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12574 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12576 ['] (CR) IS CR \ ' (CR) is CR
12577 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
12579 ." RC5toLCD is running. Type STOP to quit"
12580 \ NOECHO \ uncomment to run this app without terminal connexion
12581 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
12582 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
12586 : STOP \ stops multitasking, must to be used before downloading app
12587 ['] (WARM) IS WARM \ remove START app from FORTH init process
12588 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
12596 CODE MAX \ n1 n2 -- n3 signed maximum
12597 CMP @PSP,TOS \ n2-n1
12598 S< ?GOTO FW1 \ n2<n1
12604 CODE MIN \ n1 n2 -- n3 signed minimum
12605 CMP @PSP,TOS \ n2-n1
12606 S< ?GOTO BW1 \ n2<n1
12612 : U.R \ u n -- display u unsigned in n width (n >= 2)
12614 R> OVER - 0 MAX SPACES TYPE
12618 CODE 20_US \ n -- n * 20 us
12619 BEGIN \ 3 cycles loop + 6~
12620 \ MOV #5,W \ 3 MCLK = 1 MHz
12621 \ MOV #23,W \ 3 MCLK = 4 MHz
12622 MOV #51,W \ 3 MCLK = 8 MHz
12623 \ MOV #104,W \ 3 MCLK = 16 MHz
12624 \ MOV #158,W \ 3 MCLK = 24 MHz
12625 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
12635 CODE TOP_LCD \ LCD Sample
12636 \ \ if write : %xxxxWWWW --
12637 \ \ if read : -- %0000RRRR
12638 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12639 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12640 0= IF \ write LCD bits pattern
12641 AND.B #LCD_DB,TOS \
12642 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12643 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12646 THEN \ read LCD bits pattern
12649 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12650 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12651 AND.B #LCD_DB,TOS \
12656 CODE LCD_W \ byte -- write byte to LCD
12658 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
12659 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
12660 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12661 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12662 COLON \ high level word starts here
12663 TOP_LCD 2 20_US \ write high nibble first
12668 CODE LCD_WrC \ char -- Write Char
12669 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12674 CODE LCD_WrF \ func -- Write Fonction
12675 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12681 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
12686 $02 LCD_WrF 100 20_us
12690 \ : LCD_Entry_set $04 OR LCD_WrF ;
12692 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
12694 \ : LCD_Display_Shift $10 OR LCD_WrF ;
12696 \ : LCD_Fn_Set $20 OR LCD_WrF ;
12698 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
12700 \ : LCD_Goto $80 OR LCD_WrF ;
12702 \ CODE LCD_R \ -- byte read byte from LCD
12703 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12704 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12705 \ COLON \ starts a FORTH word
12706 \ TOP_LCD 2 20_us \ -- %0000HHHH
12707 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
12708 \ HI2LO \ switch from FORTH to assembler
12709 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
12710 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
12711 \ MOV @RSP+,IP \ restore IP saved by COLON
12716 \ CODE LCD_RdS \ -- status Read Status
12717 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12722 \ CODE LCD_RdC \ -- char Read Char
12723 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12728 \ -------------+------+------+------+------++---+---+---+---+---------+
12729 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
12730 \ -------------+------+------+------+------++---+---+---+---+---------+
12731 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
12732 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
12733 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
12734 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
12735 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
12736 \ -------------+------+------+------+------++---+---+---+---+---------+
12739 \ ******************************\
12740 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12741 \ ******************************\
12742 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
12743 \ ------------------------------\
12744 \ define LPM mode for ACCEPT \
12745 \ ------------------------------\
12746 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12747 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12748 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12749 BIT.B #SW2,&SW2_IN \ test switch S2
12750 0= IF \ case of switch S2 pressed
12751 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
12753 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
12756 BIT.B #SW1,&SW1_IN \ test switch S1 input
12757 0= IF \ case of Switch S1 pressed
12758 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
12760 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
12764 RETI \ CPU is ON, GIE is OFF
12769 \ ------------------------------\
12770 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12771 \ ******************************\
12772 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12773 \ ******************************\
12774 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12775 \ \ SMclock = 8|16|24 MHz
12776 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
12777 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
12778 \ \ SR(9)=new Toggle bit memory (ADD on)
12779 \ ------------------------------\
12780 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
12781 \ ------------------------------\
12782 \ define LPM mode for ACCEPT \
12783 \ ------------------------------\
12784 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12785 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12786 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12787 \ ------------------------------\
12788 \ RC5_FirstStartBitHalfCycle: \
12789 \ ------------------------------\
12790 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
12791 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
12792 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
12793 MOV #1778,X \ RC5_Period in us
12794 MOV #14,W \ count of loop
12796 \ ------------------------------\
12797 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
12798 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
12799 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
12800 \ RC5_Compute_3/4_Period: \ |
12801 RRUM #1,X \ X=1/2 cycle |
12805 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
12806 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
12808 \ ------------------------------\
12809 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
12810 \ ------------------------------\
12811 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12812 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
12813 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12814 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12815 SUB #1,W \ decrement count loop
12816 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
12817 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12818 0<> WHILE \ ----> out of loop ----+
12819 \ RC5_compute_7/4_Time_out: \ |
12820 ADD X,Y \ | out of bound = 7/4 period
12821 \ RC5_WaitHalfCycleP1.2_IFG: \ |
12823 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
12824 0>= IF \ | if cycle time out of bound
12825 BIC #$30,&TA0CTL \ | stop timer_A0
12826 RETI \ | then quit to do nothing
12828 \ ------------------------------\ |
12829 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
12831 MOV &TA0R,X \ | | get new RC5_period value
12832 REPEAT \ ----> loop back --+ |
12833 \ ------------------------------\ |
12834 \ RC5_SampleEndOf: \ <---------------------+
12835 \ ------------------------------\
12836 BIC #$30,&TA0CTL \ stop timer_A0
12837 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
12838 \ ******************************\
12839 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12840 \ ******************************\
12841 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
12842 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
12843 XOR IP,X \ (new XOR old) Toggle bit (13)
12844 BIT #BIT13,X \ X(13) = New_RC5_command
12845 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
12847 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
12848 \ ******************************\
12849 \ RC5_ComputeNewRC5word \
12850 \ ******************************\
12852 MOV &BASE,2(PSP) \ save variable BASE before use
12853 MOV TOS,0(PSP) \ save TOS before use
12854 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
12855 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
12856 \ ******************************\
12857 \ RC5_ComputeC6bit \
12858 \ ******************************\
12859 BIT #$4000,IP \ test /C6 bit in IP
12860 0= IF BIS #$40,TOS \ set C6 bit in S
12861 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
12862 \ ******************************\
12863 \ RC5_CommandByteIsDone \ RC5_code --
12864 \ ******************************\
12866 \ ------------------------------\
12867 \ Display IR_RC5 code \
12868 \ ------------------------------\
12869 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
12870 \ ------------------------------\
12871 LO2HI \ switch from assembler to FORTH
12872 ['] LCD_CLEAR IS CR \ redirects CR
12873 ['] LCD_WrC IS EMIT \ redirects EMIT
12874 $10 BASE ! \ change BASE to hexadecimal
12875 CR ." $" 2 U.R \ print IR_RC5 code
12876 ['] (CR) IS CR \ restore CR
12877 ['] (EMIT) IS EMIT \ restore EMIT
12878 HI2LO \ switch from FORTH to assembler
12879 \ ------------------------------\
12880 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
12881 \ ------------------------------\
12882 MOV @PSP+,&BASE \ restore variable BASE
12883 RETI \ CPU is ON, GIE is OFF
12888 \ ------------------------------\
12889 \ TB0CTL = %0000 0010 1001 0100\$3C0
12890 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12891 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12892 \ -- \ID input divider \ 10 = /4
12893 \ -- \MC Mode Control \ 01 = up to TB0CCR0
12894 \ - \TBCLR TimerB Clear
12897 \ --------------------------------\\
12898 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12899 \ -- \CM Capture Mode
12904 \ --- \OUTMOD \ 011 = set/reset
12910 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
12912 \ ------------------------------\
12913 \ set TimerB to make 50kHz PWM \
12914 \ ------------------------------\
12915 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12916 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
12917 \ ------------------------------\
12918 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
12919 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
12920 \ ------------------------------\
12921 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12922 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
12923 \ ------------------------------\
12924 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12925 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
12926 \ ------------------------------\
12927 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
12928 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
12929 \ ------------------------------\
12930 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
12931 \ ------------------------------\
12932 \ set TimerB to generate PWM for LCD_Vo
12933 \ ------------------------------\
12934 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
12935 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
12936 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12937 \ ------------------------------\
12938 BIS.B #LCDVo,&LCDVo_DIR \
12939 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
12940 \ ------------------------------\
12941 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12942 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12943 \ ------------------------------\
12944 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12945 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12946 \ ------------------------------\
12947 \ WDT interval init part \
12948 \ ------------------------------\
12949 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
12950 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
12951 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
12952 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
12953 \ ------------------------------\
12955 \ ------------------------------\
12956 BIS.B #RC5,&IR_IE \ enable RC5_Int
12957 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12958 \ ------------------------------\
12959 \ init interrupt vectors
12960 \ ------------------------------\
12961 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
12962 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12963 \ ------------------------------\
12964 \ define LPM mode for ACCEPT \
12965 \ ------------------------------\
12966 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12967 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12968 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12970 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
12972 \ ------------------------------\
12974 \ ------------------------------\
12975 $03E8 20_US \ 1- wait 20 ms
12976 $03 TOP_LCD \ 2- send DB5=DB4=1
12977 $CD 20_US \ 3- wait 4,1 ms
12978 $03 TOP_LCD \ 4- send again DB5=DB4=1
12979 $5 20_US \ 5- wait 0,1 ms
12980 $03 TOP_LCD \ 6- send again again DB5=DB4=1
12981 $2 20_US \ wait 40 us = LCD cycle
12982 $02 TOP_LCD \ 7- send DB5=1 DB4=0
12983 $2 20_US \ wait 40 us = LCD cycle
12984 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12985 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12986 LCD_Clear \ 10- "LCD_Clear"
12987 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12988 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12989 LCD_Clear \ 10- "LCD_Clear"
12990 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12991 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12993 ['] (CR) IS CR \ ' (CR) is CR
12994 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
12996 ." RC5toLCD is running. Type STOP to quit"
12997 \ NOECHO \ uncomment to run this app without terminal connexion
12998 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
12999 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
13003 : STOP \ stops multitasking, must to be used before downloading app
13004 ['] (WARM) IS WARM \ remove START app from FORTH init process
13005 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
13013 CODE MAX \ n1 n2 -- n3 signed maximum
13014 CMP @PSP,TOS \ n2-n1
13015 S< ?GOTO FW1 \ n2<n1
13021 CODE MIN \ n1 n2 -- n3 signed minimum
13022 CMP @PSP,TOS \ n2-n1
13023 S< ?GOTO BW1 \ n2<n1
13029 : U.R \ u n -- display u unsigned in n width (n >= 2)
13031 R> OVER - 0 MAX SPACES TYPE
13035 CODE 20_US \ n -- n * 20 us
13036 BEGIN \ 3 cycles loop + 6~
13037 \ MOV #5,W \ 3 MCLK = 1 MHz
13038 \ MOV #23,W \ 3 MCLK = 4 MHz
13039 MOV #51,W \ 3 MCLK = 8 MHz
13040 \ MOV #104,W \ 3 MCLK = 16 MHz
13041 \ MOV #158,W \ 3 MCLK = 24 MHz
13042 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
13052 CODE TOP_LCD \ LCD Sample
13053 \ \ if write : %xxxxWWWW --
13054 \ \ if read : -- %0000RRRR
13055 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13056 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13057 0= IF \ write LCD bits pattern
13058 AND.B #LCD_DB,TOS \
13059 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13060 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13063 THEN \ read LCD bits pattern
13066 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13067 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13068 AND.B #LCD_DB,TOS \
13073 CODE LCD_W \ byte -- write byte to LCD
13075 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13076 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13077 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13078 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13079 COLON \ high level word starts here
13080 TOP_LCD 2 20_US \ write high nibble first
13085 CODE LCD_WrC \ char -- Write Char
13086 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13091 CODE LCD_WrF \ func -- Write Fonction
13092 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13098 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
13103 $02 LCD_WrF 100 20_us
13107 \ : LCD_Entry_set $04 OR LCD_WrF ;
13109 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
13111 \ : LCD_Display_Shift $10 OR LCD_WrF ;
13113 \ : LCD_Fn_Set $20 OR LCD_WrF ;
13115 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
13117 \ : LCD_Goto $80 OR LCD_WrF ;
13119 \ CODE LCD_R \ -- byte read byte from LCD
13120 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13121 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13122 \ COLON \ starts a FORTH word
13123 \ TOP_LCD 2 20_us \ -- %0000HHHH
13124 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13125 \ HI2LO \ switch from FORTH to assembler
13126 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13127 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13128 \ MOV @RSP+,IP \ restore IP saved by COLON
13133 \ CODE LCD_RdS \ -- status Read Status
13134 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13139 \ CODE LCD_RdC \ -- char Read Char
13140 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13145 \ -------------+------+------+------+------++---+---+---+---+---------+
13146 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
13147 \ -------------+------+------+------+------++---+---+---+---+---------+
13148 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
13149 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
13150 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
13151 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
13152 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
13153 \ -------------+------+------+------+------++---+---+---+---+---------+
13156 \ ******************************\
13157 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13158 \ ******************************\
13159 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
13160 \ ------------------------------\
13161 \ define LPM mode for ACCEPT \
13162 \ ------------------------------\
13163 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13164 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13165 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13166 BIT.B #SW2,&SW2_IN \ test switch S2
13167 0= IF \ case of switch S2 pressed
13168 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
13170 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
13173 BIT.B #SW1,&SW1_IN \ test switch S1 input
13174 0= IF \ case of Switch S1 pressed
13175 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
13177 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
13181 RETI \ CPU is ON, GIE is OFF
13186 \ ------------------------------\
13187 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13188 \ ******************************\
13189 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13190 \ ******************************\
13191 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13192 \ \ SMclock = 8|16|24 MHz
13193 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
13194 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
13195 \ \ SR(9)=new Toggle bit memory (ADD on)
13196 \ ------------------------------\
13197 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
13198 \ ------------------------------\
13199 \ define LPM mode for ACCEPT \
13200 \ ------------------------------\
13201 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13202 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13203 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13204 \ ------------------------------\
13205 \ RC5_FirstStartBitHalfCycle: \
13206 \ ------------------------------\
13207 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
13208 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
13209 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
13210 MOV #1778,X \ RC5_Period in us
13211 MOV #14,W \ count of loop
13213 \ ------------------------------\
13214 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
13215 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
13216 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
13217 \ RC5_Compute_3/4_Period: \ |
13218 RRUM #1,X \ X=1/2 cycle |
13222 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
13223 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
13225 \ ------------------------------\
13226 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
13227 \ ------------------------------\
13228 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13229 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
13230 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13231 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13232 SUB #1,W \ decrement count loop
13233 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
13234 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13235 0<> WHILE \ ----> out of loop ----+
13236 \ RC5_compute_7/4_Time_out: \ |
13237 ADD X,Y \ | out of bound = 7/4 period
13238 \ RC5_WaitHalfCycleP1.2_IFG: \ |
13240 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
13241 0>= IF \ | if cycle time out of bound
13242 BIC #$30,&TA0CTL \ | stop timer_A0
13243 RETI \ | then quit to do nothing
13245 \ ------------------------------\ |
13246 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
13248 MOV &TA0R,X \ | | get new RC5_period value
13249 REPEAT \ ----> loop back --+ |
13250 \ ------------------------------\ |
13251 \ RC5_SampleEndOf: \ <---------------------+
13252 \ ------------------------------\
13253 BIC #$30,&TA0CTL \ stop timer_A0
13254 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
13255 \ ******************************\
13256 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13257 \ ******************************\
13258 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
13259 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
13260 XOR IP,X \ (new XOR old) Toggle bit (13)
13261 BIT #BIT13,X \ X(13) = New_RC5_command
13262 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
13264 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
13265 \ ******************************\
13266 \ RC5_ComputeNewRC5word \
13267 \ ******************************\
13269 MOV &BASE,2(PSP) \ save variable BASE before use
13270 MOV TOS,0(PSP) \ save TOS before use
13271 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
13272 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
13273 \ ******************************\
13274 \ RC5_ComputeC6bit \
13275 \ ******************************\
13276 BIT #$4000,IP \ test /C6 bit in IP
13277 0= IF BIS #$40,TOS \ set C6 bit in S
13278 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
13279 \ ******************************\
13280 \ RC5_CommandByteIsDone \ RC5_code --
13281 \ ******************************\
13283 \ ------------------------------\
13284 \ Display IR_RC5 code \
13285 \ ------------------------------\
13286 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
13287 \ ------------------------------\
13288 LO2HI \ switch from assembler to FORTH
13289 ['] LCD_CLEAR IS CR \ redirects CR
13290 ['] LCD_WrC IS EMIT \ redirects EMIT
13291 $10 BASE ! \ change BASE to hexadecimal
13292 CR ." $" 2 U.R \ print IR_RC5 code
13293 ['] (CR) IS CR \ restore CR
13294 ['] (EMIT) IS EMIT \ restore EMIT
13295 HI2LO \ switch from FORTH to assembler
13296 \ ------------------------------\
13297 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
13298 \ ------------------------------\
13299 MOV @PSP+,&BASE \ restore variable BASE
13300 RETI \ CPU is ON, GIE is OFF
13305 \ ------------------------------\
13306 \ TB0CTL = %0000 0010 1001 0100\$3C0
13307 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13308 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13309 \ -- \ID input divider \ 10 = /4
13310 \ -- \MC Mode Control \ 01 = up to TB0CCR0
13311 \ - \TBCLR TimerB Clear
13314 \ --------------------------------\\
13315 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13316 \ -- \CM Capture Mode
13321 \ --- \OUTMOD \ 011 = set/reset
13327 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
13329 \ ------------------------------\
13330 \ set TimerB to make 50kHz PWM \
13331 \ ------------------------------\
13332 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13333 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
13334 \ ------------------------------\
13335 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13336 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
13337 \ ------------------------------\
13338 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13339 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
13340 \ ------------------------------\
13341 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13342 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
13343 \ ------------------------------\
13344 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13345 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
13346 \ ------------------------------\
13347 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
13348 \ ------------------------------\
13349 \ set TimerB to generate PWM for LCD_Vo
13350 \ ------------------------------\
13351 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
13352 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
13353 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13354 \ ------------------------------\
13355 BIS.B #LCDVo,&LCDVo_DIR \
13356 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
13357 \ ------------------------------\
13358 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13359 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13360 \ ------------------------------\
13361 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13362 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13363 \ ------------------------------\
13364 \ WDT interval init part \
13365 \ ------------------------------\
13366 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
13367 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
13368 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
13369 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
13370 \ ------------------------------\
13372 \ ------------------------------\
13373 BIS.B #RC5,&IR_IE \ enable RC5_Int
13374 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13375 \ ------------------------------\
13376 \ init interrupt vectors
13377 \ ------------------------------\
13378 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
13379 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13380 \ ------------------------------\
13381 \ define LPM mode for ACCEPT \
13382 \ ------------------------------\
13383 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13384 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13385 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13387 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
13389 \ ------------------------------\
13391 \ ------------------------------\
13392 $03E8 20_US \ 1- wait 20 ms
13393 $03 TOP_LCD \ 2- send DB5=DB4=1
13394 $CD 20_US \ 3- wait 4,1 ms
13395 $03 TOP_LCD \ 4- send again DB5=DB4=1
13396 $5 20_US \ 5- wait 0,1 ms
13397 $03 TOP_LCD \ 6- send again again DB5=DB4=1
13398 $2 20_US \ wait 40 us = LCD cycle
13399 $02 TOP_LCD \ 7- send DB5=1 DB4=0
13400 $2 20_US \ wait 40 us = LCD cycle
13401 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13402 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13403 LCD_Clear \ 10- "LCD_Clear"
13404 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13405 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13406 LCD_Clear \ 10- "LCD_Clear"
13407 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13408 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13410 ['] (CR) IS CR \ ' (CR) is CR
13411 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
13413 ." RC5toLCD is running. Type STOP to quit"
13414 \ NOECHO \ uncomment to run this app without terminal connexion
13415 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
13416 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
13420 : STOP \ stops multitasking, must to be used before downloading app
13421 ['] (WARM) IS WARM \ remove START app from FORTH init process
13422 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
13430 CODE MAX \ n1 n2 -- n3 signed maximum
13431 CMP @PSP,TOS \ n2-n1
13432 S< ?GOTO FW1 \ n2<n1
13438 CODE MIN \ n1 n2 -- n3 signed minimum
13439 CMP @PSP,TOS \ n2-n1
13440 S< ?GOTO BW1 \ n2<n1
13446 : U.R \ u n -- display u unsigned in n width (n >= 2)
13448 R> OVER - 0 MAX SPACES TYPE
13452 CODE 20_US \ n -- n * 20 us
13453 BEGIN \ 3 cycles loop + 6~
13454 \ MOV #5,W \ 3 MCLK = 1 MHz
13455 \ MOV #23,W \ 3 MCLK = 4 MHz
13456 MOV #51,W \ 3 MCLK = 8 MHz
13457 \ MOV #104,W \ 3 MCLK = 16 MHz
13458 \ MOV #158,W \ 3 MCLK = 24 MHz
13459 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
13469 CODE TOP_LCD \ LCD Sample
13470 \ \ if write : %xxxxWWWW --
13471 \ \ if read : -- %0000RRRR
13472 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13473 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13474 0= IF \ write LCD bits pattern
13475 AND.B #LCD_DB,TOS \
13476 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13477 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13480 THEN \ read LCD bits pattern
13483 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13484 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13485 AND.B #LCD_DB,TOS \
13490 CODE LCD_W \ byte -- write byte to LCD
13492 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13493 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13494 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13495 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13496 COLON \ high level word starts here
13497 TOP_LCD 2 20_US \ write high nibble first
13502 CODE LCD_WrC \ char -- Write Char
13503 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13508 CODE LCD_WrF \ func -- Write Fonction
13509 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13515 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
13520 $02 LCD_WrF 100 20_us
13524 \ : LCD_Entry_set $04 OR LCD_WrF ;
13526 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
13528 \ : LCD_Display_Shift $10 OR LCD_WrF ;
13530 \ : LCD_Fn_Set $20 OR LCD_WrF ;
13532 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
13534 \ : LCD_Goto $80 OR LCD_WrF ;
13536 \ CODE LCD_R \ -- byte read byte from LCD
13537 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13538 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13539 \ COLON \ starts a FORTH word
13540 \ TOP_LCD 2 20_us \ -- %0000HHHH
13541 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13542 \ HI2LO \ switch from FORTH to assembler
13543 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13544 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13545 \ MOV @RSP+,IP \ restore IP saved by COLON
13550 \ CODE LCD_RdS \ -- status Read Status
13551 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13556 \ CODE LCD_RdC \ -- char Read Char
13557 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13562 \ -------------+------+------+------+------++---+---+---+---+---------+
13563 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
13564 \ -------------+------+------+------+------++---+---+---+---+---------+
13565 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
13566 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
13567 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
13568 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
13569 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
13570 \ -------------+------+------+------+------++---+---+---+---+---------+
13573 \ ******************************\
13574 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13575 \ ******************************\
13576 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
13577 \ ------------------------------\
13578 \ define LPM mode for ACCEPT \
13579 \ ------------------------------\
13580 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13581 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13582 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13583 BIT.B #SW2,&SW2_IN \ test switch S2
13584 0= IF \ case of switch S2 pressed
13585 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
13587 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
13590 BIT.B #SW1,&SW1_IN \ test switch S1 input
13591 0= IF \ case of Switch S1 pressed
13592 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
13594 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
13598 RETI \ CPU is ON, GIE is OFF
13603 \ ------------------------------\
13604 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13605 \ ******************************\
13606 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13607 \ ******************************\
13608 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13609 \ \ SMclock = 8|16|24 MHz
13610 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
13611 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
13612 \ \ SR(9)=new Toggle bit memory (ADD on)
13613 \ ------------------------------\
13614 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
13615 \ ------------------------------\
13616 \ define LPM mode for ACCEPT \
13617 \ ------------------------------\
13618 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13619 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13620 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13621 \ ------------------------------\
13622 \ RC5_FirstStartBitHalfCycle: \
13623 \ ------------------------------\
13624 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
13625 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
13626 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
13627 MOV #1778,X \ RC5_Period in us
13628 MOV #14,W \ count of loop
13630 \ ------------------------------\
13631 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
13632 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
13633 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
13634 \ RC5_Compute_3/4_Period: \ |
13635 RRUM #1,X \ X=1/2 cycle |
13639 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
13640 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
13642 \ ------------------------------\
13643 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
13644 \ ------------------------------\
13645 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13646 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
13647 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13648 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13649 SUB #1,W \ decrement count loop
13650 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
13651 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13652 0<> WHILE \ ----> out of loop ----+
13653 \ RC5_compute_7/4_Time_out: \ |
13654 ADD X,Y \ | out of bound = 7/4 period
13655 \ RC5_WaitHalfCycleP1.2_IFG: \ |
13657 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
13658 0>= IF \ | if cycle time out of bound
13659 BIC #$30,&TA0CTL \ | stop timer_A0
13660 RETI \ | then quit to do nothing
13662 \ ------------------------------\ |
13663 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
13665 MOV &TA0R,X \ | | get new RC5_period value
13666 REPEAT \ ----> loop back --+ |
13667 \ ------------------------------\ |
13668 \ RC5_SampleEndOf: \ <---------------------+
13669 \ ------------------------------\
13670 BIC #$30,&TA0CTL \ stop timer_A0
13671 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
13672 \ ******************************\
13673 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13674 \ ******************************\
13675 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
13676 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
13677 XOR IP,X \ (new XOR old) Toggle bit (13)
13678 BIT #BIT13,X \ X(13) = New_RC5_command
13679 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
13681 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
13682 \ ******************************\
13683 \ RC5_ComputeNewRC5word \
13684 \ ******************************\
13686 MOV &BASE,2(PSP) \ save variable BASE before use
13687 MOV TOS,0(PSP) \ save TOS before use
13688 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
13689 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
13690 \ ******************************\
13691 \ RC5_ComputeC6bit \
13692 \ ******************************\
13693 BIT #$4000,IP \ test /C6 bit in IP
13694 0= IF BIS #$40,TOS \ set C6 bit in S
13695 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
13696 \ ******************************\
13697 \ RC5_CommandByteIsDone \ RC5_code --
13698 \ ******************************\
13700 \ ------------------------------\
13701 \ Display IR_RC5 code \
13702 \ ------------------------------\
13703 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
13704 \ ------------------------------\
13705 LO2HI \ switch from assembler to FORTH
13706 ['] LCD_CLEAR IS CR \ redirects CR
13707 ['] LCD_WrC IS EMIT \ redirects EMIT
13708 $10 BASE ! \ change BASE to hexadecimal
13709 CR ." $" 2 U.R \ print IR_RC5 code
13710 ['] (CR) IS CR \ restore CR
13711 ['] (EMIT) IS EMIT \ restore EMIT
13712 HI2LO \ switch from FORTH to assembler
13713 \ ------------------------------\
13714 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
13715 \ ------------------------------\
13716 MOV @PSP+,&BASE \ restore variable BASE
13717 RETI \ CPU is ON, GIE is OFF
13722 \ ------------------------------\
13723 \ TB0CTL = %0000 0010 1001 0100\$3C0
13724 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13725 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13726 \ -- \ID input divider \ 10 = /4
13727 \ -- \MC Mode Control \ 01 = up to TB0CCR0
13728 \ - \TBCLR TimerB Clear
13731 \ --------------------------------\\
13732 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13733 \ -- \CM Capture Mode
13738 \ --- \OUTMOD \ 011 = set/reset
13744 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
13746 \ ------------------------------\
13747 \ set TimerB to make 50kHz PWM \
13748 \ ------------------------------\
13749 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13750 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
13751 \ ------------------------------\
13752 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
13753 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
13754 \ ------------------------------\
13755 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13756 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
13757 \ ------------------------------\
13758 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13759 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
13760 \ ------------------------------\
13761 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
13762 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
13763 \ ------------------------------\
13764 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
13765 \ ------------------------------\
13766 \ set TimerB to generate PWM for LCD_Vo
13767 \ ------------------------------\
13768 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
13769 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
13770 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13771 \ ------------------------------\
13772 BIS.B #LCDVo,&LCDVo_DIR \
13773 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
13774 \ ------------------------------\
13775 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13776 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13777 \ ------------------------------\
13778 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13779 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13780 \ ------------------------------\
13781 \ WDT interval init part \
13782 \ ------------------------------\
13783 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
13784 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
13785 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
13786 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
13787 \ ------------------------------\
13789 \ ------------------------------\
13790 BIS.B #RC5,&IR_IE \ enable RC5_Int
13791 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13792 \ ------------------------------\
13793 \ init interrupt vectors
13794 \ ------------------------------\
13795 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
13796 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13797 \ ------------------------------\
13798 \ define LPM mode for ACCEPT \
13799 \ ------------------------------\
13800 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13801 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13802 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13804 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
13806 \ ------------------------------\
13808 \ ------------------------------\
13809 $03E8 20_US \ 1- wait 20 ms
13810 $03 TOP_LCD \ 2- send DB5=DB4=1
13811 $CD 20_US \ 3- wait 4,1 ms
13812 $03 TOP_LCD \ 4- send again DB5=DB4=1
13813 $5 20_US \ 5- wait 0,1 ms
13814 $03 TOP_LCD \ 6- send again again DB5=DB4=1
13815 $2 20_US \ wait 40 us = LCD cycle
13816 $02 TOP_LCD \ 7- send DB5=1 DB4=0
13817 $2 20_US \ wait 40 us = LCD cycle
13818 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13819 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13820 LCD_Clear \ 10- "LCD_Clear"
13821 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13822 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13823 LCD_Clear \ 10- "LCD_Clear"
13824 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13825 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13827 ['] (CR) IS CR \ ' (CR) is CR
13828 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
13830 ." RC5toLCD is running. Type STOP to quit"
13831 \ NOECHO \ uncomment to run this app without terminal connexion
13832 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
13833 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
13837 : STOP \ stops multitasking, must to be used before downloading app
13838 ['] (WARM) IS WARM \ remove START app from FORTH init process
13839 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
13847 CODE MAX \ n1 n2 -- n3 signed maximum
13848 CMP @PSP,TOS \ n2-n1
13849 S< ?GOTO FW1 \ n2<n1
13855 CODE MIN \ n1 n2 -- n3 signed minimum
13856 CMP @PSP,TOS \ n2-n1
13857 S< ?GOTO BW1 \ n2<n1
13863 : U.R \ u n -- display u unsigned in n width (n >= 2)
13865 R> OVER - 0 MAX SPACES TYPE
13869 CODE 20_US \ n -- n * 20 us
13870 BEGIN \ 3 cycles loop + 6~
13871 \ MOV #5,W \ 3 MCLK = 1 MHz
13872 \ MOV #23,W \ 3 MCLK = 4 MHz
13873 MOV #51,W \ 3 MCLK = 8 MHz
13874 \ MOV #104,W \ 3 MCLK = 16 MHz
13875 \ MOV #158,W \ 3 MCLK = 24 MHz
13876 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
13886 CODE TOP_LCD \ LCD Sample
13887 \ \ if write : %xxxxWWWW --
13888 \ \ if read : -- %0000RRRR
13889 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13890 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13891 0= IF \ write LCD bits pattern
13892 AND.B #LCD_DB,TOS \
13893 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13894 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13897 THEN \ read LCD bits pattern
13900 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13901 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13902 AND.B #LCD_DB,TOS \
13907 CODE LCD_W \ byte -- write byte to LCD
13909 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
13910 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
13911 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13912 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13913 COLON \ high level word starts here
13914 TOP_LCD 2 20_US \ write high nibble first
13919 CODE LCD_WrC \ char -- Write Char
13920 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13925 CODE LCD_WrF \ func -- Write Fonction
13926 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13932 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
13937 $02 LCD_WrF 100 20_us
13941 \ : LCD_Entry_set $04 OR LCD_WrF ;
13943 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
13945 \ : LCD_Display_Shift $10 OR LCD_WrF ;
13947 \ : LCD_Fn_Set $20 OR LCD_WrF ;
13949 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
13951 \ : LCD_Goto $80 OR LCD_WrF ;
13953 \ CODE LCD_R \ -- byte read byte from LCD
13954 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13955 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13956 \ COLON \ starts a FORTH word
13957 \ TOP_LCD 2 20_us \ -- %0000HHHH
13958 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
13959 \ HI2LO \ switch from FORTH to assembler
13960 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
13961 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
13962 \ MOV @RSP+,IP \ restore IP saved by COLON
13967 \ CODE LCD_RdS \ -- status Read Status
13968 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13973 \ CODE LCD_RdC \ -- char Read Char
13974 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13979 \ -------------+------+------+------+------++---+---+---+---+---------+
13980 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
13981 \ -------------+------+------+------+------++---+---+---+---+---------+
13982 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
13983 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
13984 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
13985 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
13986 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
13987 \ -------------+------+------+------+------++---+---+---+---+---------+
13990 \ ******************************\
13991 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13992 \ ******************************\
13993 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
13994 \ ------------------------------\
13995 \ define LPM mode for ACCEPT \
13996 \ ------------------------------\
13997 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13998 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13999 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14000 BIT.B #SW2,&SW2_IN \ test switch S2
14001 0= IF \ case of switch S2 pressed
14002 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
14004 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
14007 BIT.B #SW1,&SW1_IN \ test switch S1 input
14008 0= IF \ case of Switch S1 pressed
14009 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
14011 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
14015 RETI \ CPU is ON, GIE is OFF
14020 \ ------------------------------\
14021 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14022 \ ******************************\
14023 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14024 \ ******************************\
14025 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14026 \ \ SMclock = 8|16|24 MHz
14027 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
14028 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
14029 \ \ SR(9)=new Toggle bit memory (ADD on)
14030 \ ------------------------------\
14031 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
14032 \ ------------------------------\
14033 \ define LPM mode for ACCEPT \
14034 \ ------------------------------\
14035 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14036 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14037 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14038 \ ------------------------------\
14039 \ RC5_FirstStartBitHalfCycle: \
14040 \ ------------------------------\
14041 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
14042 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
14043 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
14044 MOV #1778,X \ RC5_Period in us
14045 MOV #14,W \ count of loop
14047 \ ------------------------------\
14048 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
14049 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
14050 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
14051 \ RC5_Compute_3/4_Period: \ |
14052 RRUM #1,X \ X=1/2 cycle |
14056 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
14057 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
14059 \ ------------------------------\
14060 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
14061 \ ------------------------------\
14062 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14063 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
14064 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14065 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14066 SUB #1,W \ decrement count loop
14067 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
14068 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14069 0<> WHILE \ ----> out of loop ----+
14070 \ RC5_compute_7/4_Time_out: \ |
14071 ADD X,Y \ | out of bound = 7/4 period
14072 \ RC5_WaitHalfCycleP1.2_IFG: \ |
14074 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
14075 0>= IF \ | if cycle time out of bound
14076 BIC #$30,&TA0CTL \ | stop timer_A0
14077 RETI \ | then quit to do nothing
14079 \ ------------------------------\ |
14080 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
14082 MOV &TA0R,X \ | | get new RC5_period value
14083 REPEAT \ ----> loop back --+ |
14084 \ ------------------------------\ |
14085 \ RC5_SampleEndOf: \ <---------------------+
14086 \ ------------------------------\
14087 BIC #$30,&TA0CTL \ stop timer_A0
14088 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
14089 \ ******************************\
14090 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14091 \ ******************************\
14092 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
14093 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
14094 XOR IP,X \ (new XOR old) Toggle bit (13)
14095 BIT #BIT13,X \ X(13) = New_RC5_command
14096 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
14098 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
14099 \ ******************************\
14100 \ RC5_ComputeNewRC5word \
14101 \ ******************************\
14103 MOV &BASE,2(PSP) \ save variable BASE before use
14104 MOV TOS,0(PSP) \ save TOS before use
14105 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
14106 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
14107 \ ******************************\
14108 \ RC5_ComputeC6bit \
14109 \ ******************************\
14110 BIT #$4000,IP \ test /C6 bit in IP
14111 0= IF BIS #$40,TOS \ set C6 bit in S
14112 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
14113 \ ******************************\
14114 \ RC5_CommandByteIsDone \ RC5_code --
14115 \ ******************************\
14117 \ ------------------------------\
14118 \ Display IR_RC5 code \
14119 \ ------------------------------\
14120 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
14121 \ ------------------------------\
14122 LO2HI \ switch from assembler to FORTH
14123 ['] LCD_CLEAR IS CR \ redirects CR
14124 ['] LCD_WrC IS EMIT \ redirects EMIT
14125 $10 BASE ! \ change BASE to hexadecimal
14126 CR ." $" 2 U.R \ print IR_RC5 code
14127 ['] (CR) IS CR \ restore CR
14128 ['] (EMIT) IS EMIT \ restore EMIT
14129 HI2LO \ switch from FORTH to assembler
14130 \ ------------------------------\
14131 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
14132 \ ------------------------------\
14133 MOV @PSP+,&BASE \ restore variable BASE
14134 RETI \ CPU is ON, GIE is OFF
14139 \ ------------------------------\
14140 \ TB0CTL = %0000 0010 1001 0100\$3C0
14141 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14142 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14143 \ -- \ID input divider \ 10 = /4
14144 \ -- \MC Mode Control \ 01 = up to TB0CCR0
14145 \ - \TBCLR TimerB Clear
14148 \ --------------------------------\\
14149 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14150 \ -- \CM Capture Mode
14155 \ --- \OUTMOD \ 011 = set/reset
14161 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
14163 \ ------------------------------\
14164 \ set TimerB to make 50kHz PWM \
14165 \ ------------------------------\
14166 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14167 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
14168 \ ------------------------------\
14169 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14170 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
14171 \ ------------------------------\
14172 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14173 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
14174 \ ------------------------------\
14175 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14176 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
14177 \ ------------------------------\
14178 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14179 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
14180 \ ------------------------------\
14181 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
14182 \ ------------------------------\
14183 \ set TimerB to generate PWM for LCD_Vo
14184 \ ------------------------------\
14185 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
14186 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
14187 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14188 \ ------------------------------\
14189 BIS.B #LCDVo,&LCDVo_DIR \
14190 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
14191 \ ------------------------------\
14192 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14193 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14194 \ ------------------------------\
14195 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14196 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14197 \ ------------------------------\
14198 \ WDT interval init part \
14199 \ ------------------------------\
14200 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
14201 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
14202 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
14203 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
14204 \ ------------------------------\
14206 \ ------------------------------\
14207 BIS.B #RC5,&IR_IE \ enable RC5_Int
14208 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14209 \ ------------------------------\
14210 \ init interrupt vectors
14211 \ ------------------------------\
14212 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
14213 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14214 \ ------------------------------\
14215 \ define LPM mode for ACCEPT \
14216 \ ------------------------------\
14217 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14218 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14219 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14221 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
14223 \ ------------------------------\
14225 \ ------------------------------\
14226 $03E8 20_US \ 1- wait 20 ms
14227 $03 TOP_LCD \ 2- send DB5=DB4=1
14228 $CD 20_US \ 3- wait 4,1 ms
14229 $03 TOP_LCD \ 4- send again DB5=DB4=1
14230 $5 20_US \ 5- wait 0,1 ms
14231 $03 TOP_LCD \ 6- send again again DB5=DB4=1
14232 $2 20_US \ wait 40 us = LCD cycle
14233 $02 TOP_LCD \ 7- send DB5=1 DB4=0
14234 $2 20_US \ wait 40 us = LCD cycle
14235 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14236 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14237 LCD_Clear \ 10- "LCD_Clear"
14238 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14239 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14240 LCD_Clear \ 10- "LCD_Clear"
14241 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14242 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14244 ['] (CR) IS CR \ ' (CR) is CR
14245 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
14247 ." RC5toLCD is running. Type STOP to quit"
14248 \ NOECHO \ uncomment to run this app without terminal connexion
14249 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
14250 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
14254 : STOP \ stops multitasking, must to be used before downloading app
14255 ['] (WARM) IS WARM \ remove START app from FORTH init process
14256 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
14264 CODE MAX \ n1 n2 -- n3 signed maximum
14265 CMP @PSP,TOS \ n2-n1
14266 S< ?GOTO FW1 \ n2<n1
14272 CODE MIN \ n1 n2 -- n3 signed minimum
14273 CMP @PSP,TOS \ n2-n1
14274 S< ?GOTO BW1 \ n2<n1
14280 : U.R \ u n -- display u unsigned in n width (n >= 2)
14282 R> OVER - 0 MAX SPACES TYPE
14286 CODE 20_US \ n -- n * 20 us
14287 BEGIN \ 3 cycles loop + 6~
14288 \ MOV #5,W \ 3 MCLK = 1 MHz
14289 \ MOV #23,W \ 3 MCLK = 4 MHz
14290 MOV #51,W \ 3 MCLK = 8 MHz
14291 \ MOV #104,W \ 3 MCLK = 16 MHz
14292 \ MOV #158,W \ 3 MCLK = 24 MHz
14293 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
14303 CODE TOP_LCD \ LCD Sample
14304 \ \ if write : %xxxxWWWW --
14305 \ \ if read : -- %0000RRRR
14306 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14307 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14308 0= IF \ write LCD bits pattern
14309 AND.B #LCD_DB,TOS \
14310 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14311 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14314 THEN \ read LCD bits pattern
14317 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14318 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14319 AND.B #LCD_DB,TOS \
14324 CODE LCD_W \ byte -- write byte to LCD
14326 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
14327 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
14328 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14329 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14330 COLON \ high level word starts here
14331 TOP_LCD 2 20_US \ write high nibble first
14336 CODE LCD_WrC \ char -- Write Char
14337 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14342 CODE LCD_WrF \ func -- Write Fonction
14343 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14349 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
14354 $02 LCD_WrF 100 20_us
14358 \ : LCD_Entry_set $04 OR LCD_WrF ;
14360 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
14362 \ : LCD_Display_Shift $10 OR LCD_WrF ;
14364 \ : LCD_Fn_Set $20 OR LCD_WrF ;
14366 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
14368 \ : LCD_Goto $80 OR LCD_WrF ;
14370 \ CODE LCD_R \ -- byte read byte from LCD
14371 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14372 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14373 \ COLON \ starts a FORTH word
14374 \ TOP_LCD 2 20_us \ -- %0000HHHH
14375 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14376 \ HI2LO \ switch from FORTH to assembler
14377 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14378 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14379 \ MOV @RSP+,IP \ restore IP saved by COLON
14384 \ CODE LCD_RdS \ -- status Read Status
14385 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14390 \ CODE LCD_RdC \ -- char Read Char
14391 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14396 \ -------------+------+------+------+------++---+---+---+---+---------+
14397 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
14398 \ -------------+------+------+------+------++---+---+---+---+---------+
14399 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
14400 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
14401 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
14402 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
14403 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
14404 \ -------------+------+------+------+------++---+---+---+---+---------+
14407 \ ******************************\
14408 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14409 \ ******************************\
14410 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
14411 \ ------------------------------\
14412 \ define LPM mode for ACCEPT \
14413 \ ------------------------------\
14414 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14415 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14416 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14417 BIT.B #SW2,&SW2_IN \ test switch S2
14418 0= IF \ case of switch S2 pressed
14419 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
14421 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
14424 BIT.B #SW1,&SW1_IN \ test switch S1 input
14425 0= IF \ case of Switch S1 pressed
14426 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
14428 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
14432 RETI \ CPU is ON, GIE is OFF
14437 \ ------------------------------\
14438 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14439 \ ******************************\
14440 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14441 \ ******************************\
14442 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14443 \ \ SMclock = 8|16|24 MHz
14444 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
14445 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
14446 \ \ SR(9)=new Toggle bit memory (ADD on)
14447 \ ------------------------------\
14448 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
14449 \ ------------------------------\
14450 \ define LPM mode for ACCEPT \
14451 \ ------------------------------\
14452 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14453 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14454 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14455 \ ------------------------------\
14456 \ RC5_FirstStartBitHalfCycle: \
14457 \ ------------------------------\
14458 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
14459 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
14460 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
14461 MOV #1778,X \ RC5_Period in us
14462 MOV #14,W \ count of loop
14464 \ ------------------------------\
14465 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
14466 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
14467 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
14468 \ RC5_Compute_3/4_Period: \ |
14469 RRUM #1,X \ X=1/2 cycle |
14473 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
14474 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
14476 \ ------------------------------\
14477 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
14478 \ ------------------------------\
14479 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14480 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
14481 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14482 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14483 SUB #1,W \ decrement count loop
14484 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
14485 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14486 0<> WHILE \ ----> out of loop ----+
14487 \ RC5_compute_7/4_Time_out: \ |
14488 ADD X,Y \ | out of bound = 7/4 period
14489 \ RC5_WaitHalfCycleP1.2_IFG: \ |
14491 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
14492 0>= IF \ | if cycle time out of bound
14493 BIC #$30,&TA0CTL \ | stop timer_A0
14494 RETI \ | then quit to do nothing
14496 \ ------------------------------\ |
14497 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
14499 MOV &TA0R,X \ | | get new RC5_period value
14500 REPEAT \ ----> loop back --+ |
14501 \ ------------------------------\ |
14502 \ RC5_SampleEndOf: \ <---------------------+
14503 \ ------------------------------\
14504 BIC #$30,&TA0CTL \ stop timer_A0
14505 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
14506 \ ******************************\
14507 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14508 \ ******************************\
14509 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
14510 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
14511 XOR IP,X \ (new XOR old) Toggle bit (13)
14512 BIT #BIT13,X \ X(13) = New_RC5_command
14513 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
14515 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
14516 \ ******************************\
14517 \ RC5_ComputeNewRC5word \
14518 \ ******************************\
14520 MOV &BASE,2(PSP) \ save variable BASE before use
14521 MOV TOS,0(PSP) \ save TOS before use
14522 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
14523 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
14524 \ ******************************\
14525 \ RC5_ComputeC6bit \
14526 \ ******************************\
14527 BIT #$4000,IP \ test /C6 bit in IP
14528 0= IF BIS #$40,TOS \ set C6 bit in S
14529 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
14530 \ ******************************\
14531 \ RC5_CommandByteIsDone \ RC5_code --
14532 \ ******************************\
14534 \ ------------------------------\
14535 \ Display IR_RC5 code \
14536 \ ------------------------------\
14537 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
14538 \ ------------------------------\
14539 LO2HI \ switch from assembler to FORTH
14540 ['] LCD_CLEAR IS CR \ redirects CR
14541 ['] LCD_WrC IS EMIT \ redirects EMIT
14542 $10 BASE ! \ change BASE to hexadecimal
14543 CR ." $" 2 U.R \ print IR_RC5 code
14544 ['] (CR) IS CR \ restore CR
14545 ['] (EMIT) IS EMIT \ restore EMIT
14546 HI2LO \ switch from FORTH to assembler
14547 \ ------------------------------\
14548 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
14549 \ ------------------------------\
14550 MOV @PSP+,&BASE \ restore variable BASE
14551 RETI \ CPU is ON, GIE is OFF
14556 \ ------------------------------\
14557 \ TB0CTL = %0000 0010 1001 0100\$3C0
14558 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14559 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14560 \ -- \ID input divider \ 10 = /4
14561 \ -- \MC Mode Control \ 01 = up to TB0CCR0
14562 \ - \TBCLR TimerB Clear
14565 \ --------------------------------\\
14566 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14567 \ -- \CM Capture Mode
14572 \ --- \OUTMOD \ 011 = set/reset
14578 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
14580 \ ------------------------------\
14581 \ set TimerB to make 50kHz PWM \
14582 \ ------------------------------\
14583 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14584 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
14585 \ ------------------------------\
14586 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
14587 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
14588 \ ------------------------------\
14589 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14590 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
14591 \ ------------------------------\
14592 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14593 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
14594 \ ------------------------------\
14595 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
14596 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
14597 \ ------------------------------\
14598 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
14599 \ ------------------------------\
14600 \ set TimerB to generate PWM for LCD_Vo
14601 \ ------------------------------\
14602 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
14603 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
14604 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14605 \ ------------------------------\
14606 BIS.B #LCDVo,&LCDVo_DIR \
14607 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
14608 \ ------------------------------\
14609 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14610 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14611 \ ------------------------------\
14612 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14613 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14614 \ ------------------------------\
14615 \ WDT interval init part \
14616 \ ------------------------------\
14617 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
14618 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
14619 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
14620 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
14621 \ ------------------------------\
14623 \ ------------------------------\
14624 BIS.B #RC5,&IR_IE \ enable RC5_Int
14625 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14626 \ ------------------------------\
14627 \ init interrupt vectors
14628 \ ------------------------------\
14629 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
14630 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14631 \ ------------------------------\
14632 \ define LPM mode for ACCEPT \
14633 \ ------------------------------\
14634 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14635 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14636 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14638 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
14640 \ ------------------------------\
14642 \ ------------------------------\
14643 $03E8 20_US \ 1- wait 20 ms
14644 $03 TOP_LCD \ 2- send DB5=DB4=1
14645 $CD 20_US \ 3- wait 4,1 ms
14646 $03 TOP_LCD \ 4- send again DB5=DB4=1
14647 $5 20_US \ 5- wait 0,1 ms
14648 $03 TOP_LCD \ 6- send again again DB5=DB4=1
14649 $2 20_US \ wait 40 us = LCD cycle
14650 $02 TOP_LCD \ 7- send DB5=1 DB4=0
14651 $2 20_US \ wait 40 us = LCD cycle
14652 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14653 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14654 LCD_Clear \ 10- "LCD_Clear"
14655 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14656 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14657 LCD_Clear \ 10- "LCD_Clear"
14658 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14659 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14661 ['] (CR) IS CR \ ' (CR) is CR
14662 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
14664 ." RC5toLCD is running. Type STOP to quit"
14665 \ NOECHO \ uncomment to run this app without terminal connexion
14666 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
14667 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
14671 : STOP \ stops multitasking, must to be used before downloading app
14672 ['] (WARM) IS WARM \ remove START app from FORTH init process
14673 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
14681 CODE MAX \ n1 n2 -- n3 signed maximum
14682 CMP @PSP,TOS \ n2-n1
14683 S< ?GOTO FW1 \ n2<n1
14689 CODE MIN \ n1 n2 -- n3 signed minimum
14690 CMP @PSP,TOS \ n2-n1
14691 S< ?GOTO BW1 \ n2<n1
14697 : U.R \ u n -- display u unsigned in n width (n >= 2)
14699 R> OVER - 0 MAX SPACES TYPE
14703 CODE 20_US \ n -- n * 20 us
14704 BEGIN \ 3 cycles loop + 6~
14705 \ MOV #5,W \ 3 MCLK = 1 MHz
14706 \ MOV #23,W \ 3 MCLK = 4 MHz
14707 MOV #51,W \ 3 MCLK = 8 MHz
14708 \ MOV #104,W \ 3 MCLK = 16 MHz
14709 \ MOV #158,W \ 3 MCLK = 24 MHz
14710 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
14720 CODE TOP_LCD \ LCD Sample
14721 \ \ if write : %xxxxWWWW --
14722 \ \ if read : -- %0000RRRR
14723 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14724 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14725 0= IF \ write LCD bits pattern
14726 AND.B #LCD_DB,TOS \
14727 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14728 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14731 THEN \ read LCD bits pattern
14734 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14735 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14736 AND.B #LCD_DB,TOS \
14741 CODE LCD_W \ byte -- write byte to LCD
14743 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
14744 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
14745 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14746 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14747 COLON \ high level word starts here
14748 TOP_LCD 2 20_US \ write high nibble first
14753 CODE LCD_WrC \ char -- Write Char
14754 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14759 CODE LCD_WrF \ func -- Write Fonction
14760 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14766 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
14771 $02 LCD_WrF 100 20_us
14775 \ : LCD_Entry_set $04 OR LCD_WrF ;
14777 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
14779 \ : LCD_Display_Shift $10 OR LCD_WrF ;
14781 \ : LCD_Fn_Set $20 OR LCD_WrF ;
14783 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
14785 \ : LCD_Goto $80 OR LCD_WrF ;
14787 \ CODE LCD_R \ -- byte read byte from LCD
14788 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14789 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14790 \ COLON \ starts a FORTH word
14791 \ TOP_LCD 2 20_us \ -- %0000HHHH
14792 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
14793 \ HI2LO \ switch from FORTH to assembler
14794 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
14795 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
14796 \ MOV @RSP+,IP \ restore IP saved by COLON
14801 \ CODE LCD_RdS \ -- status Read Status
14802 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14807 \ CODE LCD_RdC \ -- char Read Char
14808 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14813 \ -------------+------+------+------+------++---+---+---+---+---------+
14814 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
14815 \ -------------+------+------+------+------++---+---+---+---+---------+
14816 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
14817 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
14818 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
14819 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
14820 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
14821 \ -------------+------+------+------+------++---+---+---+---+---------+
14824 \ ******************************\
14825 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14826 \ ******************************\
14827 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
14828 \ ------------------------------\
14829 \ define LPM mode for ACCEPT \
14830 \ ------------------------------\
14831 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14832 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14833 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14834 BIT.B #SW2,&SW2_IN \ test switch S2
14835 0= IF \ case of switch S2 pressed
14836 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
14838 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
14841 BIT.B #SW1,&SW1_IN \ test switch S1 input
14842 0= IF \ case of Switch S1 pressed
14843 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
14845 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
14849 RETI \ CPU is ON, GIE is OFF
14854 \ ------------------------------\
14855 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14856 \ ******************************\
14857 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14858 \ ******************************\
14859 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14860 \ \ SMclock = 8|16|24 MHz
14861 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
14862 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
14863 \ \ SR(9)=new Toggle bit memory (ADD on)
14864 \ ------------------------------\
14865 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
14866 \ ------------------------------\
14867 \ define LPM mode for ACCEPT \
14868 \ ------------------------------\
14869 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14870 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14871 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14872 \ ------------------------------\
14873 \ RC5_FirstStartBitHalfCycle: \
14874 \ ------------------------------\
14875 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
14876 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
14877 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
14878 MOV #1778,X \ RC5_Period in us
14879 MOV #14,W \ count of loop
14881 \ ------------------------------\
14882 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
14883 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
14884 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
14885 \ RC5_Compute_3/4_Period: \ |
14886 RRUM #1,X \ X=1/2 cycle |
14890 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
14891 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
14893 \ ------------------------------\
14894 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
14895 \ ------------------------------\
14896 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14897 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
14898 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14899 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14900 SUB #1,W \ decrement count loop
14901 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
14902 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14903 0<> WHILE \ ----> out of loop ----+
14904 \ RC5_compute_7/4_Time_out: \ |
14905 ADD X,Y \ | out of bound = 7/4 period
14906 \ RC5_WaitHalfCycleP1.2_IFG: \ |
14908 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
14909 0>= IF \ | if cycle time out of bound
14910 BIC #$30,&TA0CTL \ | stop timer_A0
14911 RETI \ | then quit to do nothing
14913 \ ------------------------------\ |
14914 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
14916 MOV &TA0R,X \ | | get new RC5_period value
14917 REPEAT \ ----> loop back --+ |
14918 \ ------------------------------\ |
14919 \ RC5_SampleEndOf: \ <---------------------+
14920 \ ------------------------------\
14921 BIC #$30,&TA0CTL \ stop timer_A0
14922 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
14923 \ ******************************\
14924 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14925 \ ******************************\
14926 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
14927 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
14928 XOR IP,X \ (new XOR old) Toggle bit (13)
14929 BIT #BIT13,X \ X(13) = New_RC5_command
14930 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
14932 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
14933 \ ******************************\
14934 \ RC5_ComputeNewRC5word \
14935 \ ******************************\
14937 MOV &BASE,2(PSP) \ save variable BASE before use
14938 MOV TOS,0(PSP) \ save TOS before use
14939 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
14940 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
14941 \ ******************************\
14942 \ RC5_ComputeC6bit \
14943 \ ******************************\
14944 BIT #$4000,IP \ test /C6 bit in IP
14945 0= IF BIS #$40,TOS \ set C6 bit in S
14946 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
14947 \ ******************************\
14948 \ RC5_CommandByteIsDone \ RC5_code --
14949 \ ******************************\
14951 \ ------------------------------\
14952 \ Display IR_RC5 code \
14953 \ ------------------------------\
14954 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
14955 \ ------------------------------\
14956 LO2HI \ switch from assembler to FORTH
14957 ['] LCD_CLEAR IS CR \ redirects CR
14958 ['] LCD_WrC IS EMIT \ redirects EMIT
14959 $10 BASE ! \ change BASE to hexadecimal
14960 CR ." $" 2 U.R \ print IR_RC5 code
14961 ['] (CR) IS CR \ restore CR
14962 ['] (EMIT) IS EMIT \ restore EMIT
14963 HI2LO \ switch from FORTH to assembler
14964 \ ------------------------------\
14965 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
14966 \ ------------------------------\
14967 MOV @PSP+,&BASE \ restore variable BASE
14968 RETI \ CPU is ON, GIE is OFF
14973 \ ------------------------------\
14974 \ TB0CTL = %0000 0010 1001 0100\$3C0
14975 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14976 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14977 \ -- \ID input divider \ 10 = /4
14978 \ -- \MC Mode Control \ 01 = up to TB0CCR0
14979 \ - \TBCLR TimerB Clear
14982 \ --------------------------------\\
14983 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14984 \ -- \CM Capture Mode
14989 \ --- \OUTMOD \ 011 = set/reset
14995 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
14997 \ ------------------------------\
14998 \ set TimerB to make 50kHz PWM \
14999 \ ------------------------------\
15000 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15001 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
15002 \ ------------------------------\
15003 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15004 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
15005 \ ------------------------------\
15006 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15007 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
15008 \ ------------------------------\
15009 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15010 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
15011 \ ------------------------------\
15012 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15013 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
15014 \ ------------------------------\
15015 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
15016 \ ------------------------------\
15017 \ set TimerB to generate PWM for LCD_Vo
15018 \ ------------------------------\
15019 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
15020 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
15021 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15022 \ ------------------------------\
15023 BIS.B #LCDVo,&LCDVo_DIR \
15024 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
15025 \ ------------------------------\
15026 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15027 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15028 \ ------------------------------\
15029 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15030 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15031 \ ------------------------------\
15032 \ WDT interval init part \
15033 \ ------------------------------\
15034 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
15035 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
15036 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
15037 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
15038 \ ------------------------------\
15040 \ ------------------------------\
15041 BIS.B #RC5,&IR_IE \ enable RC5_Int
15042 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15043 \ ------------------------------\
15044 \ init interrupt vectors
15045 \ ------------------------------\
15046 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
15047 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15048 \ ------------------------------\
15049 \ define LPM mode for ACCEPT \
15050 \ ------------------------------\
15051 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15052 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15053 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15055 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
15057 \ ------------------------------\
15059 \ ------------------------------\
15060 $03E8 20_US \ 1- wait 20 ms
15061 $03 TOP_LCD \ 2- send DB5=DB4=1
15062 $CD 20_US \ 3- wait 4,1 ms
15063 $03 TOP_LCD \ 4- send again DB5=DB4=1
15064 $5 20_US \ 5- wait 0,1 ms
15065 $03 TOP_LCD \ 6- send again again DB5=DB4=1
15066 $2 20_US \ wait 40 us = LCD cycle
15067 $02 TOP_LCD \ 7- send DB5=1 DB4=0
15068 $2 20_US \ wait 40 us = LCD cycle
15069 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15070 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15071 LCD_Clear \ 10- "LCD_Clear"
15072 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15073 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15074 LCD_Clear \ 10- "LCD_Clear"
15075 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15076 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15078 ['] (CR) IS CR \ ' (CR) is CR
15079 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
15081 ." RC5toLCD is running. Type STOP to quit"
15082 \ NOECHO \ uncomment to run this app without terminal connexion
15083 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
15084 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
15088 : STOP \ stops multitasking, must to be used before downloading app
15089 ['] (WARM) IS WARM \ remove START app from FORTH init process
15090 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
15098 CODE MAX \ n1 n2 -- n3 signed maximum
15099 CMP @PSP,TOS \ n2-n1
15100 S< ?GOTO FW1 \ n2<n1
15106 CODE MIN \ n1 n2 -- n3 signed minimum
15107 CMP @PSP,TOS \ n2-n1
15108 S< ?GOTO BW1 \ n2<n1
15114 : U.R \ u n -- display u unsigned in n width (n >= 2)
15116 R> OVER - 0 MAX SPACES TYPE
15120 CODE 20_US \ n -- n * 20 us
15121 BEGIN \ 3 cycles loop + 6~
15122 \ MOV #5,W \ 3 MCLK = 1 MHz
15123 \ MOV #23,W \ 3 MCLK = 4 MHz
15124 MOV #51,W \ 3 MCLK = 8 MHz
15125 \ MOV #104,W \ 3 MCLK = 16 MHz
15126 \ MOV #158,W \ 3 MCLK = 24 MHz
15127 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
15137 CODE TOP_LCD \ LCD Sample
15138 \ \ if write : %xxxxWWWW --
15139 \ \ if read : -- %0000RRRR
15140 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15141 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15142 0= IF \ write LCD bits pattern
15143 AND.B #LCD_DB,TOS \
15144 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15145 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15148 THEN \ read LCD bits pattern
15151 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15152 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15153 AND.B #LCD_DB,TOS \
15158 CODE LCD_W \ byte -- write byte to LCD
15160 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15161 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15162 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15163 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15164 COLON \ high level word starts here
15165 TOP_LCD 2 20_US \ write high nibble first
15170 CODE LCD_WrC \ char -- Write Char
15171 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15176 CODE LCD_WrF \ func -- Write Fonction
15177 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15183 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
15188 $02 LCD_WrF 100 20_us
15192 \ : LCD_Entry_set $04 OR LCD_WrF ;
15194 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
15196 \ : LCD_Display_Shift $10 OR LCD_WrF ;
15198 \ : LCD_Fn_Set $20 OR LCD_WrF ;
15200 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
15202 \ : LCD_Goto $80 OR LCD_WrF ;
15204 \ CODE LCD_R \ -- byte read byte from LCD
15205 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15206 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15207 \ COLON \ starts a FORTH word
15208 \ TOP_LCD 2 20_us \ -- %0000HHHH
15209 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
15210 \ HI2LO \ switch from FORTH to assembler
15211 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
15212 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
15213 \ MOV @RSP+,IP \ restore IP saved by COLON
15218 \ CODE LCD_RdS \ -- status Read Status
15219 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15224 \ CODE LCD_RdC \ -- char Read Char
15225 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15230 \ -------------+------+------+------+------++---+---+---+---+---------+
15231 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
15232 \ -------------+------+------+------+------++---+---+---+---+---------+
15233 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
15234 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
15235 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
15236 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
15237 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
15238 \ -------------+------+------+------+------++---+---+---+---+---------+
15241 \ ******************************\
15242 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15243 \ ******************************\
15244 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
15245 \ ------------------------------\
15246 \ define LPM mode for ACCEPT \
15247 \ ------------------------------\
15248 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15249 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15250 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15251 BIT.B #SW2,&SW2_IN \ test switch S2
15252 0= IF \ case of switch S2 pressed
15253 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
15255 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
15258 BIT.B #SW1,&SW1_IN \ test switch S1 input
15259 0= IF \ case of Switch S1 pressed
15260 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
15262 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
15266 RETI \ CPU is ON, GIE is OFF
15271 \ ------------------------------\
15272 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15273 \ ******************************\
15274 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15275 \ ******************************\
15276 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15277 \ \ SMclock = 8|16|24 MHz
15278 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
15279 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
15280 \ \ SR(9)=new Toggle bit memory (ADD on)
15281 \ ------------------------------\
15282 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
15283 \ ------------------------------\
15284 \ define LPM mode for ACCEPT \
15285 \ ------------------------------\
15286 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15287 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15288 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15289 \ ------------------------------\
15290 \ RC5_FirstStartBitHalfCycle: \
15291 \ ------------------------------\
15292 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
15293 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
15294 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
15295 MOV #1778,X \ RC5_Period in us
15296 MOV #14,W \ count of loop
15298 \ ------------------------------\
15299 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
15300 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
15301 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
15302 \ RC5_Compute_3/4_Period: \ |
15303 RRUM #1,X \ X=1/2 cycle |
15307 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
15308 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
15310 \ ------------------------------\
15311 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
15312 \ ------------------------------\
15313 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15314 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
15315 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15316 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15317 SUB #1,W \ decrement count loop
15318 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
15319 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15320 0<> WHILE \ ----> out of loop ----+
15321 \ RC5_compute_7/4_Time_out: \ |
15322 ADD X,Y \ | out of bound = 7/4 period
15323 \ RC5_WaitHalfCycleP1.2_IFG: \ |
15325 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
15326 0>= IF \ | if cycle time out of bound
15327 BIC #$30,&TA0CTL \ | stop timer_A0
15328 RETI \ | then quit to do nothing
15330 \ ------------------------------\ |
15331 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
15333 MOV &TA0R,X \ | | get new RC5_period value
15334 REPEAT \ ----> loop back --+ |
15335 \ ------------------------------\ |
15336 \ RC5_SampleEndOf: \ <---------------------+
15337 \ ------------------------------\
15338 BIC #$30,&TA0CTL \ stop timer_A0
15339 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
15340 \ ******************************\
15341 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15342 \ ******************************\
15343 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
15344 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
15345 XOR IP,X \ (new XOR old) Toggle bit (13)
15346 BIT #BIT13,X \ X(13) = New_RC5_command
15347 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
15349 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
15350 \ ******************************\
15351 \ RC5_ComputeNewRC5word \
15352 \ ******************************\
15354 MOV &BASE,2(PSP) \ save variable BASE before use
15355 MOV TOS,0(PSP) \ save TOS before use
15356 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
15357 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
15358 \ ******************************\
15359 \ RC5_ComputeC6bit \
15360 \ ******************************\
15361 BIT #$4000,IP \ test /C6 bit in IP
15362 0= IF BIS #$40,TOS \ set C6 bit in S
15363 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
15364 \ ******************************\
15365 \ RC5_CommandByteIsDone \ RC5_code --
15366 \ ******************************\
15368 \ ------------------------------\
15369 \ Display IR_RC5 code \
15370 \ ------------------------------\
15371 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
15372 \ ------------------------------\
15373 LO2HI \ switch from assembler to FORTH
15374 ['] LCD_CLEAR IS CR \ redirects CR
15375 ['] LCD_WrC IS EMIT \ redirects EMIT
15376 $10 BASE ! \ change BASE to hexadecimal
15377 CR ." $" 2 U.R \ print IR_RC5 code
15378 ['] (CR) IS CR \ restore CR
15379 ['] (EMIT) IS EMIT \ restore EMIT
15380 HI2LO \ switch from FORTH to assembler
15381 \ ------------------------------\
15382 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
15383 \ ------------------------------\
15384 MOV @PSP+,&BASE \ restore variable BASE
15385 RETI \ CPU is ON, GIE is OFF
15390 \ ------------------------------\
15391 \ TB0CTL = %0000 0010 1001 0100\$3C0
15392 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15393 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15394 \ -- \ID input divider \ 10 = /4
15395 \ -- \MC Mode Control \ 01 = up to TB0CCR0
15396 \ - \TBCLR TimerB Clear
15399 \ --------------------------------\\
15400 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15401 \ -- \CM Capture Mode
15406 \ --- \OUTMOD \ 011 = set/reset
15412 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
15414 \ ------------------------------\
15415 \ set TimerB to make 50kHz PWM \
15416 \ ------------------------------\
15417 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15418 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
15419 \ ------------------------------\
15420 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15421 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
15422 \ ------------------------------\
15423 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15424 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
15425 \ ------------------------------\
15426 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15427 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
15428 \ ------------------------------\
15429 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15430 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
15431 \ ------------------------------\
15432 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
15433 \ ------------------------------\
15434 \ set TimerB to generate PWM for LCD_Vo
15435 \ ------------------------------\
15436 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
15437 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
15438 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15439 \ ------------------------------\
15440 BIS.B #LCDVo,&LCDVo_DIR \
15441 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
15442 \ ------------------------------\
15443 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15444 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15445 \ ------------------------------\
15446 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15447 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15448 \ ------------------------------\
15449 \ WDT interval init part \
15450 \ ------------------------------\
15451 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
15452 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
15453 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
15454 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
15455 \ ------------------------------\
15457 \ ------------------------------\
15458 BIS.B #RC5,&IR_IE \ enable RC5_Int
15459 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15460 \ ------------------------------\
15461 \ init interrupt vectors
15462 \ ------------------------------\
15463 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
15464 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15465 \ ------------------------------\
15466 \ define LPM mode for ACCEPT \
15467 \ ------------------------------\
15468 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15469 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15470 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15472 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
15474 \ ------------------------------\
15476 \ ------------------------------\
15477 $03E8 20_US \ 1- wait 20 ms
15478 $03 TOP_LCD \ 2- send DB5=DB4=1
15479 $CD 20_US \ 3- wait 4,1 ms
15480 $03 TOP_LCD \ 4- send again DB5=DB4=1
15481 $5 20_US \ 5- wait 0,1 ms
15482 $03 TOP_LCD \ 6- send again again DB5=DB4=1
15483 $2 20_US \ wait 40 us = LCD cycle
15484 $02 TOP_LCD \ 7- send DB5=1 DB4=0
15485 $2 20_US \ wait 40 us = LCD cycle
15486 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15487 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15488 LCD_Clear \ 10- "LCD_Clear"
15489 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15490 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15491 LCD_Clear \ 10- "LCD_Clear"
15492 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15493 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15495 ['] (CR) IS CR \ ' (CR) is CR
15496 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
15498 ." RC5toLCD is running. Type STOP to quit"
15499 \ NOECHO \ uncomment to run this app without terminal connexion
15500 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
15501 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
15505 : STOP \ stops multitasking, must to be used before downloading app
15506 ['] (WARM) IS WARM \ remove START app from FORTH init process
15507 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
15515 CODE MAX \ n1 n2 -- n3 signed maximum
15516 CMP @PSP,TOS \ n2-n1
15517 S< ?GOTO FW1 \ n2<n1
15523 CODE MIN \ n1 n2 -- n3 signed minimum
15524 CMP @PSP,TOS \ n2-n1
15525 S< ?GOTO BW1 \ n2<n1
15531 : U.R \ u n -- display u unsigned in n width (n >= 2)
15533 R> OVER - 0 MAX SPACES TYPE
15537 CODE 20_US \ n -- n * 20 us
15538 BEGIN \ 3 cycles loop + 6~
15539 \ MOV #5,W \ 3 MCLK = 1 MHz
15540 \ MOV #23,W \ 3 MCLK = 4 MHz
15541 MOV #51,W \ 3 MCLK = 8 MHz
15542 \ MOV #104,W \ 3 MCLK = 16 MHz
15543 \ MOV #158,W \ 3 MCLK = 24 MHz
15544 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
15554 CODE TOP_LCD \ LCD Sample
15555 \ \ if write : %xxxxWWWW --
15556 \ \ if read : -- %0000RRRR
15557 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15558 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15559 0= IF \ write LCD bits pattern
15560 AND.B #LCD_DB,TOS \
15561 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15562 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15565 THEN \ read LCD bits pattern
15568 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15569 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15570 AND.B #LCD_DB,TOS \
15575 CODE LCD_W \ byte -- write byte to LCD
15577 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15578 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15579 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15580 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15581 COLON \ high level word starts here
15582 TOP_LCD 2 20_US \ write high nibble first
15587 CODE LCD_WrC \ char -- Write Char
15588 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15593 CODE LCD_WrF \ func -- Write Fonction
15594 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15600 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
15605 $02 LCD_WrF 100 20_us
15609 \ : LCD_Entry_set $04 OR LCD_WrF ;
15611 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
15613 \ : LCD_Display_Shift $10 OR LCD_WrF ;
15615 \ : LCD_Fn_Set $20 OR LCD_WrF ;
15617 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
15619 \ : LCD_Goto $80 OR LCD_WrF ;
15621 \ CODE LCD_R \ -- byte read byte from LCD
15622 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15623 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15624 \ COLON \ starts a FORTH word
15625 \ TOP_LCD 2 20_us \ -- %0000HHHH
15626 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
15627 \ HI2LO \ switch from FORTH to assembler
15628 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
15629 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
15630 \ MOV @RSP+,IP \ restore IP saved by COLON
15635 \ CODE LCD_RdS \ -- status Read Status
15636 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15641 \ CODE LCD_RdC \ -- char Read Char
15642 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15647 \ -------------+------+------+------+------++---+---+---+---+---------+
15648 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
15649 \ -------------+------+------+------+------++---+---+---+---+---------+
15650 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
15651 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
15652 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
15653 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
15654 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
15655 \ -------------+------+------+------+------++---+---+---+---+---------+
15658 \ ******************************\
15659 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15660 \ ******************************\
15661 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
15662 \ ------------------------------\
15663 \ define LPM mode for ACCEPT \
15664 \ ------------------------------\
15665 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15666 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15667 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15668 BIT.B #SW2,&SW2_IN \ test switch S2
15669 0= IF \ case of switch S2 pressed
15670 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
15672 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
15675 BIT.B #SW1,&SW1_IN \ test switch S1 input
15676 0= IF \ case of Switch S1 pressed
15677 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
15679 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
15683 RETI \ CPU is ON, GIE is OFF
15688 \ ------------------------------\
15689 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15690 \ ******************************\
15691 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15692 \ ******************************\
15693 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15694 \ \ SMclock = 8|16|24 MHz
15695 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
15696 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
15697 \ \ SR(9)=new Toggle bit memory (ADD on)
15698 \ ------------------------------\
15699 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
15700 \ ------------------------------\
15701 \ define LPM mode for ACCEPT \
15702 \ ------------------------------\
15703 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15704 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15705 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15706 \ ------------------------------\
15707 \ RC5_FirstStartBitHalfCycle: \
15708 \ ------------------------------\
15709 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
15710 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
15711 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
15712 MOV #1778,X \ RC5_Period in us
15713 MOV #14,W \ count of loop
15715 \ ------------------------------\
15716 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
15717 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
15718 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
15719 \ RC5_Compute_3/4_Period: \ |
15720 RRUM #1,X \ X=1/2 cycle |
15724 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
15725 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
15727 \ ------------------------------\
15728 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
15729 \ ------------------------------\
15730 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15731 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
15732 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15733 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15734 SUB #1,W \ decrement count loop
15735 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
15736 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15737 0<> WHILE \ ----> out of loop ----+
15738 \ RC5_compute_7/4_Time_out: \ |
15739 ADD X,Y \ | out of bound = 7/4 period
15740 \ RC5_WaitHalfCycleP1.2_IFG: \ |
15742 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
15743 0>= IF \ | if cycle time out of bound
15744 BIC #$30,&TA0CTL \ | stop timer_A0
15745 RETI \ | then quit to do nothing
15747 \ ------------------------------\ |
15748 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
15750 MOV &TA0R,X \ | | get new RC5_period value
15751 REPEAT \ ----> loop back --+ |
15752 \ ------------------------------\ |
15753 \ RC5_SampleEndOf: \ <---------------------+
15754 \ ------------------------------\
15755 BIC #$30,&TA0CTL \ stop timer_A0
15756 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
15757 \ ******************************\
15758 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15759 \ ******************************\
15760 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
15761 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
15762 XOR IP,X \ (new XOR old) Toggle bit (13)
15763 BIT #BIT13,X \ X(13) = New_RC5_command
15764 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
15766 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
15767 \ ******************************\
15768 \ RC5_ComputeNewRC5word \
15769 \ ******************************\
15771 MOV &BASE,2(PSP) \ save variable BASE before use
15772 MOV TOS,0(PSP) \ save TOS before use
15773 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
15774 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
15775 \ ******************************\
15776 \ RC5_ComputeC6bit \
15777 \ ******************************\
15778 BIT #$4000,IP \ test /C6 bit in IP
15779 0= IF BIS #$40,TOS \ set C6 bit in S
15780 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
15781 \ ******************************\
15782 \ RC5_CommandByteIsDone \ RC5_code --
15783 \ ******************************\
15785 \ ------------------------------\
15786 \ Display IR_RC5 code \
15787 \ ------------------------------\
15788 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
15789 \ ------------------------------\
15790 LO2HI \ switch from assembler to FORTH
15791 ['] LCD_CLEAR IS CR \ redirects CR
15792 ['] LCD_WrC IS EMIT \ redirects EMIT
15793 $10 BASE ! \ change BASE to hexadecimal
15794 CR ." $" 2 U.R \ print IR_RC5 code
15795 ['] (CR) IS CR \ restore CR
15796 ['] (EMIT) IS EMIT \ restore EMIT
15797 HI2LO \ switch from FORTH to assembler
15798 \ ------------------------------\
15799 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
15800 \ ------------------------------\
15801 MOV @PSP+,&BASE \ restore variable BASE
15802 RETI \ CPU is ON, GIE is OFF
15807 \ ------------------------------\
15808 \ TB0CTL = %0000 0010 1001 0100\$3C0
15809 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15810 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15811 \ -- \ID input divider \ 10 = /4
15812 \ -- \MC Mode Control \ 01 = up to TB0CCR0
15813 \ - \TBCLR TimerB Clear
15816 \ --------------------------------\\
15817 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15818 \ -- \CM Capture Mode
15823 \ --- \OUTMOD \ 011 = set/reset
15829 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
15831 \ ------------------------------\
15832 \ set TimerB to make 50kHz PWM \
15833 \ ------------------------------\
15834 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15835 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
15836 \ ------------------------------\
15837 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
15838 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
15839 \ ------------------------------\
15840 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15841 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
15842 \ ------------------------------\
15843 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15844 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
15845 \ ------------------------------\
15846 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
15847 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
15848 \ ------------------------------\
15849 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
15850 \ ------------------------------\
15851 \ set TimerB to generate PWM for LCD_Vo
15852 \ ------------------------------\
15853 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
15854 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
15855 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15856 \ ------------------------------\
15857 BIS.B #LCDVo,&LCDVo_DIR \
15858 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
15859 \ ------------------------------\
15860 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15861 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15862 \ ------------------------------\
15863 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15864 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15865 \ ------------------------------\
15866 \ WDT interval init part \
15867 \ ------------------------------\
15868 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
15869 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
15870 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
15871 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
15872 \ ------------------------------\
15874 \ ------------------------------\
15875 BIS.B #RC5,&IR_IE \ enable RC5_Int
15876 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15877 \ ------------------------------\
15878 \ init interrupt vectors
15879 \ ------------------------------\
15880 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
15881 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15882 \ ------------------------------\
15883 \ define LPM mode for ACCEPT \
15884 \ ------------------------------\
15885 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15886 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15887 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15889 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
15891 \ ------------------------------\
15893 \ ------------------------------\
15894 $03E8 20_US \ 1- wait 20 ms
15895 $03 TOP_LCD \ 2- send DB5=DB4=1
15896 $CD 20_US \ 3- wait 4,1 ms
15897 $03 TOP_LCD \ 4- send again DB5=DB4=1
15898 $5 20_US \ 5- wait 0,1 ms
15899 $03 TOP_LCD \ 6- send again again DB5=DB4=1
15900 $2 20_US \ wait 40 us = LCD cycle
15901 $02 TOP_LCD \ 7- send DB5=1 DB4=0
15902 $2 20_US \ wait 40 us = LCD cycle
15903 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15904 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15905 LCD_Clear \ 10- "LCD_Clear"
15906 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15907 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15908 LCD_Clear \ 10- "LCD_Clear"
15909 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15910 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15912 ['] (CR) IS CR \ ' (CR) is CR
15913 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
15915 ." RC5toLCD is running. Type STOP to quit"
15916 \ NOECHO \ uncomment to run this app without terminal connexion
15917 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
15918 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
15922 : STOP \ stops multitasking, must to be used before downloading app
15923 ['] (WARM) IS WARM \ remove START app from FORTH init process
15924 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
15932 CODE MAX \ n1 n2 -- n3 signed maximum
15933 CMP @PSP,TOS \ n2-n1
15934 S< ?GOTO FW1 \ n2<n1
15940 CODE MIN \ n1 n2 -- n3 signed minimum
15941 CMP @PSP,TOS \ n2-n1
15942 S< ?GOTO BW1 \ n2<n1
15948 : U.R \ u n -- display u unsigned in n width (n >= 2)
15950 R> OVER - 0 MAX SPACES TYPE
15954 CODE 20_US \ n -- n * 20 us
15955 BEGIN \ 3 cycles loop + 6~
15956 \ MOV #5,W \ 3 MCLK = 1 MHz
15957 \ MOV #23,W \ 3 MCLK = 4 MHz
15958 MOV #51,W \ 3 MCLK = 8 MHz
15959 \ MOV #104,W \ 3 MCLK = 16 MHz
15960 \ MOV #158,W \ 3 MCLK = 24 MHz
15961 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
15971 CODE TOP_LCD \ LCD Sample
15972 \ \ if write : %xxxxWWWW --
15973 \ \ if read : -- %0000RRRR
15974 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15975 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15976 0= IF \ write LCD bits pattern
15977 AND.B #LCD_DB,TOS \
15978 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15979 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15982 THEN \ read LCD bits pattern
15985 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15986 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15987 AND.B #LCD_DB,TOS \
15992 CODE LCD_W \ byte -- write byte to LCD
15994 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
15995 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
15996 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15997 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15998 COLON \ high level word starts here
15999 TOP_LCD 2 20_US \ write high nibble first
16004 CODE LCD_WrC \ char -- Write Char
16005 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16010 CODE LCD_WrF \ func -- Write Fonction
16011 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16017 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
16022 $02 LCD_WrF 100 20_us
16026 \ : LCD_Entry_set $04 OR LCD_WrF ;
16028 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
16030 \ : LCD_Display_Shift $10 OR LCD_WrF ;
16032 \ : LCD_Fn_Set $20 OR LCD_WrF ;
16034 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
16036 \ : LCD_Goto $80 OR LCD_WrF ;
16038 \ CODE LCD_R \ -- byte read byte from LCD
16039 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16040 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16041 \ COLON \ starts a FORTH word
16042 \ TOP_LCD 2 20_us \ -- %0000HHHH
16043 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16044 \ HI2LO \ switch from FORTH to assembler
16045 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16046 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16047 \ MOV @RSP+,IP \ restore IP saved by COLON
16052 \ CODE LCD_RdS \ -- status Read Status
16053 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16058 \ CODE LCD_RdC \ -- char Read Char
16059 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16064 \ -------------+------+------+------+------++---+---+---+---+---------+
16065 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
16066 \ -------------+------+------+------+------++---+---+---+---+---------+
16067 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
16068 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
16069 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
16070 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
16071 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
16072 \ -------------+------+------+------+------++---+---+---+---+---------+
16075 \ ******************************\
16076 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16077 \ ******************************\
16078 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
16079 \ ------------------------------\
16080 \ define LPM mode for ACCEPT \
16081 \ ------------------------------\
16082 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16083 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16084 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16085 BIT.B #SW2,&SW2_IN \ test switch S2
16086 0= IF \ case of switch S2 pressed
16087 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
16089 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
16092 BIT.B #SW1,&SW1_IN \ test switch S1 input
16093 0= IF \ case of Switch S1 pressed
16094 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
16096 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
16100 RETI \ CPU is ON, GIE is OFF
16105 \ ------------------------------\
16106 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16107 \ ******************************\
16108 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16109 \ ******************************\
16110 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16111 \ \ SMclock = 8|16|24 MHz
16112 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
16113 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
16114 \ \ SR(9)=new Toggle bit memory (ADD on)
16115 \ ------------------------------\
16116 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
16117 \ ------------------------------\
16118 \ define LPM mode for ACCEPT \
16119 \ ------------------------------\
16120 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16121 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16122 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16123 \ ------------------------------\
16124 \ RC5_FirstStartBitHalfCycle: \
16125 \ ------------------------------\
16126 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
16127 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
16128 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
16129 MOV #1778,X \ RC5_Period in us
16130 MOV #14,W \ count of loop
16132 \ ------------------------------\
16133 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
16134 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
16135 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
16136 \ RC5_Compute_3/4_Period: \ |
16137 RRUM #1,X \ X=1/2 cycle |
16141 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
16142 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
16144 \ ------------------------------\
16145 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
16146 \ ------------------------------\
16147 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16148 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
16149 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16150 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16151 SUB #1,W \ decrement count loop
16152 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
16153 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16154 0<> WHILE \ ----> out of loop ----+
16155 \ RC5_compute_7/4_Time_out: \ |
16156 ADD X,Y \ | out of bound = 7/4 period
16157 \ RC5_WaitHalfCycleP1.2_IFG: \ |
16159 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
16160 0>= IF \ | if cycle time out of bound
16161 BIC #$30,&TA0CTL \ | stop timer_A0
16162 RETI \ | then quit to do nothing
16164 \ ------------------------------\ |
16165 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
16167 MOV &TA0R,X \ | | get new RC5_period value
16168 REPEAT \ ----> loop back --+ |
16169 \ ------------------------------\ |
16170 \ RC5_SampleEndOf: \ <---------------------+
16171 \ ------------------------------\
16172 BIC #$30,&TA0CTL \ stop timer_A0
16173 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
16174 \ ******************************\
16175 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16176 \ ******************************\
16177 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
16178 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
16179 XOR IP,X \ (new XOR old) Toggle bit (13)
16180 BIT #BIT13,X \ X(13) = New_RC5_command
16181 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
16183 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
16184 \ ******************************\
16185 \ RC5_ComputeNewRC5word \
16186 \ ******************************\
16188 MOV &BASE,2(PSP) \ save variable BASE before use
16189 MOV TOS,0(PSP) \ save TOS before use
16190 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
16191 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
16192 \ ******************************\
16193 \ RC5_ComputeC6bit \
16194 \ ******************************\
16195 BIT #$4000,IP \ test /C6 bit in IP
16196 0= IF BIS #$40,TOS \ set C6 bit in S
16197 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
16198 \ ******************************\
16199 \ RC5_CommandByteIsDone \ RC5_code --
16200 \ ******************************\
16202 \ ------------------------------\
16203 \ Display IR_RC5 code \
16204 \ ------------------------------\
16205 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
16206 \ ------------------------------\
16207 LO2HI \ switch from assembler to FORTH
16208 ['] LCD_CLEAR IS CR \ redirects CR
16209 ['] LCD_WrC IS EMIT \ redirects EMIT
16210 $10 BASE ! \ change BASE to hexadecimal
16211 CR ." $" 2 U.R \ print IR_RC5 code
16212 ['] (CR) IS CR \ restore CR
16213 ['] (EMIT) IS EMIT \ restore EMIT
16214 HI2LO \ switch from FORTH to assembler
16215 \ ------------------------------\
16216 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
16217 \ ------------------------------\
16218 MOV @PSP+,&BASE \ restore variable BASE
16219 RETI \ CPU is ON, GIE is OFF
16224 \ ------------------------------\
16225 \ TB0CTL = %0000 0010 1001 0100\$3C0
16226 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16227 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16228 \ -- \ID input divider \ 10 = /4
16229 \ -- \MC Mode Control \ 01 = up to TB0CCR0
16230 \ - \TBCLR TimerB Clear
16233 \ --------------------------------\\
16234 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16235 \ -- \CM Capture Mode
16240 \ --- \OUTMOD \ 011 = set/reset
16246 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
16248 \ ------------------------------\
16249 \ set TimerB to make 50kHz PWM \
16250 \ ------------------------------\
16251 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16252 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
16253 \ ------------------------------\
16254 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16255 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
16256 \ ------------------------------\
16257 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16258 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
16259 \ ------------------------------\
16260 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16261 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
16262 \ ------------------------------\
16263 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16264 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
16265 \ ------------------------------\
16266 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
16267 \ ------------------------------\
16268 \ set TimerB to generate PWM for LCD_Vo
16269 \ ------------------------------\
16270 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
16271 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
16272 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16273 \ ------------------------------\
16274 BIS.B #LCDVo,&LCDVo_DIR \
16275 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
16276 \ ------------------------------\
16277 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16278 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16279 \ ------------------------------\
16280 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16281 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16282 \ ------------------------------\
16283 \ WDT interval init part \
16284 \ ------------------------------\
16285 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
16286 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
16287 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
16288 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
16289 \ ------------------------------\
16291 \ ------------------------------\
16292 BIS.B #RC5,&IR_IE \ enable RC5_Int
16293 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16294 \ ------------------------------\
16295 \ init interrupt vectors
16296 \ ------------------------------\
16297 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
16298 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16299 \ ------------------------------\
16300 \ define LPM mode for ACCEPT \
16301 \ ------------------------------\
16302 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16303 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16304 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16306 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
16308 \ ------------------------------\
16310 \ ------------------------------\
16311 $03E8 20_US \ 1- wait 20 ms
16312 $03 TOP_LCD \ 2- send DB5=DB4=1
16313 $CD 20_US \ 3- wait 4,1 ms
16314 $03 TOP_LCD \ 4- send again DB5=DB4=1
16315 $5 20_US \ 5- wait 0,1 ms
16316 $03 TOP_LCD \ 6- send again again DB5=DB4=1
16317 $2 20_US \ wait 40 us = LCD cycle
16318 $02 TOP_LCD \ 7- send DB5=1 DB4=0
16319 $2 20_US \ wait 40 us = LCD cycle
16320 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16321 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16322 LCD_Clear \ 10- "LCD_Clear"
16323 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16324 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16325 LCD_Clear \ 10- "LCD_Clear"
16326 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16327 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16329 ['] (CR) IS CR \ ' (CR) is CR
16330 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
16332 ." RC5toLCD is running. Type STOP to quit"
16333 \ NOECHO \ uncomment to run this app without terminal connexion
16334 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
16335 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
16339 : STOP \ stops multitasking, must to be used before downloading app
16340 ['] (WARM) IS WARM \ remove START app from FORTH init process
16341 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
16349 CODE MAX \ n1 n2 -- n3 signed maximum
16350 CMP @PSP,TOS \ n2-n1
16351 S< ?GOTO FW1 \ n2<n1
16357 CODE MIN \ n1 n2 -- n3 signed minimum
16358 CMP @PSP,TOS \ n2-n1
16359 S< ?GOTO BW1 \ n2<n1
16365 : U.R \ u n -- display u unsigned in n width (n >= 2)
16367 R> OVER - 0 MAX SPACES TYPE
16371 CODE 20_US \ n -- n * 20 us
16372 BEGIN \ 3 cycles loop + 6~
16373 \ MOV #5,W \ 3 MCLK = 1 MHz
16374 \ MOV #23,W \ 3 MCLK = 4 MHz
16375 MOV #51,W \ 3 MCLK = 8 MHz
16376 \ MOV #104,W \ 3 MCLK = 16 MHz
16377 \ MOV #158,W \ 3 MCLK = 24 MHz
16378 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
16388 CODE TOP_LCD \ LCD Sample
16389 \ \ if write : %xxxxWWWW --
16390 \ \ if read : -- %0000RRRR
16391 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16392 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16393 0= IF \ write LCD bits pattern
16394 AND.B #LCD_DB,TOS \
16395 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16396 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16399 THEN \ read LCD bits pattern
16402 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16403 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16404 AND.B #LCD_DB,TOS \
16409 CODE LCD_W \ byte -- write byte to LCD
16411 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16412 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16413 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16414 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16415 COLON \ high level word starts here
16416 TOP_LCD 2 20_US \ write high nibble first
16421 CODE LCD_WrC \ char -- Write Char
16422 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16427 CODE LCD_WrF \ func -- Write Fonction
16428 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16434 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
16439 $02 LCD_WrF 100 20_us
16443 \ : LCD_Entry_set $04 OR LCD_WrF ;
16445 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
16447 \ : LCD_Display_Shift $10 OR LCD_WrF ;
16449 \ : LCD_Fn_Set $20 OR LCD_WrF ;
16451 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
16453 \ : LCD_Goto $80 OR LCD_WrF ;
16455 \ CODE LCD_R \ -- byte read byte from LCD
16456 \ 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
16469 \ CODE LCD_RdS \ -- status Read Status
16470 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16475 \ CODE LCD_RdC \ -- char Read Char
16476 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16481 \ -------------+------+------+------+------++---+---+---+---+---------+
16482 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
16483 \ -------------+------+------+------+------++---+---+---+---+---------+
16484 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
16485 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
16486 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
16487 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
16488 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
16489 \ -------------+------+------+------+------++---+---+---+---+---------+
16492 \ ******************************\
16493 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16494 \ ******************************\
16495 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
16496 \ ------------------------------\
16497 \ define LPM mode for ACCEPT \
16498 \ ------------------------------\
16499 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16500 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16501 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16502 BIT.B #SW2,&SW2_IN \ test switch S2
16503 0= IF \ case of switch S2 pressed
16504 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
16506 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
16509 BIT.B #SW1,&SW1_IN \ test switch S1 input
16510 0= IF \ case of Switch S1 pressed
16511 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
16513 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
16517 RETI \ CPU is ON, GIE is OFF
16522 \ ------------------------------\
16523 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16524 \ ******************************\
16525 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16526 \ ******************************\
16527 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16528 \ \ SMclock = 8|16|24 MHz
16529 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
16530 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
16531 \ \ SR(9)=new Toggle bit memory (ADD on)
16532 \ ------------------------------\
16533 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
16534 \ ------------------------------\
16535 \ define LPM mode for ACCEPT \
16536 \ ------------------------------\
16537 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16538 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16539 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16540 \ ------------------------------\
16541 \ RC5_FirstStartBitHalfCycle: \
16542 \ ------------------------------\
16543 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
16544 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
16545 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
16546 MOV #1778,X \ RC5_Period in us
16547 MOV #14,W \ count of loop
16549 \ ------------------------------\
16550 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
16551 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
16552 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
16553 \ RC5_Compute_3/4_Period: \ |
16554 RRUM #1,X \ X=1/2 cycle |
16558 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
16559 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
16561 \ ------------------------------\
16562 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
16563 \ ------------------------------\
16564 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16565 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
16566 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16567 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16568 SUB #1,W \ decrement count loop
16569 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
16570 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16571 0<> WHILE \ ----> out of loop ----+
16572 \ RC5_compute_7/4_Time_out: \ |
16573 ADD X,Y \ | out of bound = 7/4 period
16574 \ RC5_WaitHalfCycleP1.2_IFG: \ |
16576 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
16577 0>= IF \ | if cycle time out of bound
16578 BIC #$30,&TA0CTL \ | stop timer_A0
16579 RETI \ | then quit to do nothing
16581 \ ------------------------------\ |
16582 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
16584 MOV &TA0R,X \ | | get new RC5_period value
16585 REPEAT \ ----> loop back --+ |
16586 \ ------------------------------\ |
16587 \ RC5_SampleEndOf: \ <---------------------+
16588 \ ------------------------------\
16589 BIC #$30,&TA0CTL \ stop timer_A0
16590 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
16591 \ ******************************\
16592 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16593 \ ******************************\
16594 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
16595 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
16596 XOR IP,X \ (new XOR old) Toggle bit (13)
16597 BIT #BIT13,X \ X(13) = New_RC5_command
16598 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
16600 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
16601 \ ******************************\
16602 \ RC5_ComputeNewRC5word \
16603 \ ******************************\
16605 MOV &BASE,2(PSP) \ save variable BASE before use
16606 MOV TOS,0(PSP) \ save TOS before use
16607 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
16608 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
16609 \ ******************************\
16610 \ RC5_ComputeC6bit \
16611 \ ******************************\
16612 BIT #$4000,IP \ test /C6 bit in IP
16613 0= IF BIS #$40,TOS \ set C6 bit in S
16614 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
16615 \ ******************************\
16616 \ RC5_CommandByteIsDone \ RC5_code --
16617 \ ******************************\
16619 \ ------------------------------\
16620 \ Display IR_RC5 code \
16621 \ ------------------------------\
16622 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
16623 \ ------------------------------\
16624 LO2HI \ switch from assembler to FORTH
16625 ['] LCD_CLEAR IS CR \ redirects CR
16626 ['] LCD_WrC IS EMIT \ redirects EMIT
16627 $10 BASE ! \ change BASE to hexadecimal
16628 CR ." $" 2 U.R \ print IR_RC5 code
16629 ['] (CR) IS CR \ restore CR
16630 ['] (EMIT) IS EMIT \ restore EMIT
16631 HI2LO \ switch from FORTH to assembler
16632 \ ------------------------------\
16633 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
16634 \ ------------------------------\
16635 MOV @PSP+,&BASE \ restore variable BASE
16636 RETI \ CPU is ON, GIE is OFF
16641 \ ------------------------------\
16642 \ TB0CTL = %0000 0010 1001 0100\$3C0
16643 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16644 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16645 \ -- \ID input divider \ 10 = /4
16646 \ -- \MC Mode Control \ 01 = up to TB0CCR0
16647 \ - \TBCLR TimerB Clear
16650 \ --------------------------------\\
16651 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16652 \ -- \CM Capture Mode
16657 \ --- \OUTMOD \ 011 = set/reset
16663 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
16665 \ ------------------------------\
16666 \ set TimerB to make 50kHz PWM \
16667 \ ------------------------------\
16668 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16669 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
16670 \ ------------------------------\
16671 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
16672 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
16673 \ ------------------------------\
16674 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16675 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
16676 \ ------------------------------\
16677 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16678 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
16679 \ ------------------------------\
16680 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
16681 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
16682 \ ------------------------------\
16683 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
16684 \ ------------------------------\
16685 \ set TimerB to generate PWM for LCD_Vo
16686 \ ------------------------------\
16687 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
16688 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
16689 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16690 \ ------------------------------\
16691 BIS.B #LCDVo,&LCDVo_DIR \
16692 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
16693 \ ------------------------------\
16694 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16695 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16696 \ ------------------------------\
16697 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16698 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16699 \ ------------------------------\
16700 \ WDT interval init part \
16701 \ ------------------------------\
16702 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
16703 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
16704 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
16705 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
16706 \ ------------------------------\
16708 \ ------------------------------\
16709 BIS.B #RC5,&IR_IE \ enable RC5_Int
16710 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16711 \ ------------------------------\
16712 \ init interrupt vectors
16713 \ ------------------------------\
16714 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
16715 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16716 \ ------------------------------\
16717 \ define LPM mode for ACCEPT \
16718 \ ------------------------------\
16719 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16720 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16721 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16723 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
16725 \ ------------------------------\
16727 \ ------------------------------\
16728 $03E8 20_US \ 1- wait 20 ms
16729 $03 TOP_LCD \ 2- send DB5=DB4=1
16730 $CD 20_US \ 3- wait 4,1 ms
16731 $03 TOP_LCD \ 4- send again DB5=DB4=1
16732 $5 20_US \ 5- wait 0,1 ms
16733 $03 TOP_LCD \ 6- send again again DB5=DB4=1
16734 $2 20_US \ wait 40 us = LCD cycle
16735 $02 TOP_LCD \ 7- send DB5=1 DB4=0
16736 $2 20_US \ wait 40 us = LCD cycle
16737 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16738 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16739 LCD_Clear \ 10- "LCD_Clear"
16740 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16741 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16742 LCD_Clear \ 10- "LCD_Clear"
16743 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16744 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16746 ['] (CR) IS CR \ ' (CR) is CR
16747 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
16749 ." RC5toLCD is running. Type STOP to quit"
16750 \ NOECHO \ uncomment to run this app without terminal connexion
16751 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
16752 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
16756 : STOP \ stops multitasking, must to be used before downloading app
16757 ['] (WARM) IS WARM \ remove START app from FORTH init process
16758 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
16766 CODE MAX \ n1 n2 -- n3 signed maximum
16767 CMP @PSP,TOS \ n2-n1
16768 S< ?GOTO FW1 \ n2<n1
16774 CODE MIN \ n1 n2 -- n3 signed minimum
16775 CMP @PSP,TOS \ n2-n1
16776 S< ?GOTO BW1 \ n2<n1
16782 : U.R \ u n -- display u unsigned in n width (n >= 2)
16784 R> OVER - 0 MAX SPACES TYPE
16788 CODE 20_US \ n -- n * 20 us
16789 BEGIN \ 3 cycles loop + 6~
16790 \ MOV #5,W \ 3 MCLK = 1 MHz
16791 \ MOV #23,W \ 3 MCLK = 4 MHz
16792 MOV #51,W \ 3 MCLK = 8 MHz
16793 \ MOV #104,W \ 3 MCLK = 16 MHz
16794 \ MOV #158,W \ 3 MCLK = 24 MHz
16795 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
16805 CODE TOP_LCD \ LCD Sample
16806 \ \ if write : %xxxxWWWW --
16807 \ \ if read : -- %0000RRRR
16808 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16809 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16810 0= IF \ write LCD bits pattern
16811 AND.B #LCD_DB,TOS \
16812 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16813 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16816 THEN \ read LCD bits pattern
16819 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16820 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16821 AND.B #LCD_DB,TOS \
16826 CODE LCD_W \ byte -- write byte to LCD
16828 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
16829 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
16830 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16831 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16832 COLON \ high level word starts here
16833 TOP_LCD 2 20_US \ write high nibble first
16838 CODE LCD_WrC \ char -- Write Char
16839 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16844 CODE LCD_WrF \ func -- Write Fonction
16845 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16851 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
16856 $02 LCD_WrF 100 20_us
16860 \ : LCD_Entry_set $04 OR LCD_WrF ;
16862 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
16864 \ : LCD_Display_Shift $10 OR LCD_WrF ;
16866 \ : LCD_Fn_Set $20 OR LCD_WrF ;
16868 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
16870 \ : LCD_Goto $80 OR LCD_WrF ;
16872 \ CODE LCD_R \ -- byte read byte from LCD
16873 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16874 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16875 \ COLON \ starts a FORTH word
16876 \ TOP_LCD 2 20_us \ -- %0000HHHH
16877 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
16878 \ HI2LO \ switch from FORTH to assembler
16879 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
16880 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
16881 \ MOV @RSP+,IP \ restore IP saved by COLON
16886 \ CODE LCD_RdS \ -- status Read Status
16887 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16892 \ CODE LCD_RdC \ -- char Read Char
16893 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16898 \ -------------+------+------+------+------++---+---+---+---+---------+
16899 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
16900 \ -------------+------+------+------+------++---+---+---+---+---------+
16901 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
16902 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
16903 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
16904 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
16905 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
16906 \ -------------+------+------+------+------++---+---+---+---+---------+
16909 \ ******************************\
16910 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16911 \ ******************************\
16912 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
16913 \ ------------------------------\
16914 \ define LPM mode for ACCEPT \
16915 \ ------------------------------\
16916 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16917 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16918 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16919 BIT.B #SW2,&SW2_IN \ test switch S2
16920 0= IF \ case of switch S2 pressed
16921 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
16923 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
16926 BIT.B #SW1,&SW1_IN \ test switch S1 input
16927 0= IF \ case of Switch S1 pressed
16928 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
16930 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
16934 RETI \ CPU is ON, GIE is OFF
16939 \ ------------------------------\
16940 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16941 \ ******************************\
16942 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16943 \ ******************************\
16944 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16945 \ \ SMclock = 8|16|24 MHz
16946 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
16947 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
16948 \ \ SR(9)=new Toggle bit memory (ADD on)
16949 \ ------------------------------\
16950 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
16951 \ ------------------------------\
16952 \ define LPM mode for ACCEPT \
16953 \ ------------------------------\
16954 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16955 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16956 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16957 \ ------------------------------\
16958 \ RC5_FirstStartBitHalfCycle: \
16959 \ ------------------------------\
16960 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
16961 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
16962 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
16963 MOV #1778,X \ RC5_Period in us
16964 MOV #14,W \ count of loop
16966 \ ------------------------------\
16967 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
16968 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
16969 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
16970 \ RC5_Compute_3/4_Period: \ |
16971 RRUM #1,X \ X=1/2 cycle |
16975 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
16976 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
16978 \ ------------------------------\
16979 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
16980 \ ------------------------------\
16981 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16982 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
16983 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16984 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16985 SUB #1,W \ decrement count loop
16986 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
16987 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16988 0<> WHILE \ ----> out of loop ----+
16989 \ RC5_compute_7/4_Time_out: \ |
16990 ADD X,Y \ | out of bound = 7/4 period
16991 \ RC5_WaitHalfCycleP1.2_IFG: \ |
16993 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
16994 0>= IF \ | if cycle time out of bound
16995 BIC #$30,&TA0CTL \ | stop timer_A0
16996 RETI \ | then quit to do nothing
16998 \ ------------------------------\ |
16999 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
17001 MOV &TA0R,X \ | | get new RC5_period value
17002 REPEAT \ ----> loop back --+ |
17003 \ ------------------------------\ |
17004 \ RC5_SampleEndOf: \ <---------------------+
17005 \ ------------------------------\
17006 BIC #$30,&TA0CTL \ stop timer_A0
17007 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
17008 \ ******************************\
17009 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17010 \ ******************************\
17011 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
17012 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
17013 XOR IP,X \ (new XOR old) Toggle bit (13)
17014 BIT #BIT13,X \ X(13) = New_RC5_command
17015 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
17017 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
17018 \ ******************************\
17019 \ RC5_ComputeNewRC5word \
17020 \ ******************************\
17022 MOV &BASE,2(PSP) \ save variable BASE before use
17023 MOV TOS,0(PSP) \ save TOS before use
17024 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
17025 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
17026 \ ******************************\
17027 \ RC5_ComputeC6bit \
17028 \ ******************************\
17029 BIT #$4000,IP \ test /C6 bit in IP
17030 0= IF BIS #$40,TOS \ set C6 bit in S
17031 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
17032 \ ******************************\
17033 \ RC5_CommandByteIsDone \ RC5_code --
17034 \ ******************************\
17036 \ ------------------------------\
17037 \ Display IR_RC5 code \
17038 \ ------------------------------\
17039 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
17040 \ ------------------------------\
17041 LO2HI \ switch from assembler to FORTH
17042 ['] LCD_CLEAR IS CR \ redirects CR
17043 ['] LCD_WrC IS EMIT \ redirects EMIT
17044 $10 BASE ! \ change BASE to hexadecimal
17045 CR ." $" 2 U.R \ print IR_RC5 code
17046 ['] (CR) IS CR \ restore CR
17047 ['] (EMIT) IS EMIT \ restore EMIT
17048 HI2LO \ switch from FORTH to assembler
17049 \ ------------------------------\
17050 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
17051 \ ------------------------------\
17052 MOV @PSP+,&BASE \ restore variable BASE
17053 RETI \ CPU is ON, GIE is OFF
17058 \ ------------------------------\
17059 \ TB0CTL = %0000 0010 1001 0100\$3C0
17060 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17061 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17062 \ -- \ID input divider \ 10 = /4
17063 \ -- \MC Mode Control \ 01 = up to TB0CCR0
17064 \ - \TBCLR TimerB Clear
17067 \ --------------------------------\\
17068 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17069 \ -- \CM Capture Mode
17074 \ --- \OUTMOD \ 011 = set/reset
17080 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
17082 \ ------------------------------\
17083 \ set TimerB to make 50kHz PWM \
17084 \ ------------------------------\
17085 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17086 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
17087 \ ------------------------------\
17088 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17089 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
17090 \ ------------------------------\
17091 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17092 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
17093 \ ------------------------------\
17094 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17095 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
17096 \ ------------------------------\
17097 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17098 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
17099 \ ------------------------------\
17100 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
17101 \ ------------------------------\
17102 \ set TimerB to generate PWM for LCD_Vo
17103 \ ------------------------------\
17104 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
17105 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
17106 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17107 \ ------------------------------\
17108 BIS.B #LCDVo,&LCDVo_DIR \
17109 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
17110 \ ------------------------------\
17111 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17112 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17113 \ ------------------------------\
17114 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17115 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17116 \ ------------------------------\
17117 \ WDT interval init part \
17118 \ ------------------------------\
17119 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
17120 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
17121 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
17122 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
17123 \ ------------------------------\
17125 \ ------------------------------\
17126 BIS.B #RC5,&IR_IE \ enable RC5_Int
17127 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17128 \ ------------------------------\
17129 \ init interrupt vectors
17130 \ ------------------------------\
17131 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
17132 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17133 \ ------------------------------\
17134 \ define LPM mode for ACCEPT \
17135 \ ------------------------------\
17136 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17137 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17138 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17140 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
17142 \ ------------------------------\
17144 \ ------------------------------\
17145 $03E8 20_US \ 1- wait 20 ms
17146 $03 TOP_LCD \ 2- send DB5=DB4=1
17147 $CD 20_US \ 3- wait 4,1 ms
17148 $03 TOP_LCD \ 4- send again DB5=DB4=1
17149 $5 20_US \ 5- wait 0,1 ms
17150 $03 TOP_LCD \ 6- send again again DB5=DB4=1
17151 $2 20_US \ wait 40 us = LCD cycle
17152 $02 TOP_LCD \ 7- send DB5=1 DB4=0
17153 $2 20_US \ wait 40 us = LCD cycle
17154 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17155 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17156 LCD_Clear \ 10- "LCD_Clear"
17157 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17158 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17159 LCD_Clear \ 10- "LCD_Clear"
17160 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17161 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17163 ['] (CR) IS CR \ ' (CR) is CR
17164 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
17166 ." RC5toLCD is running. Type STOP to quit"
17167 \ NOECHO \ uncomment to run this app without terminal connexion
17168 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
17169 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
17173 : STOP \ stops multitasking, must to be used before downloading app
17174 ['] (WARM) IS WARM \ remove START app from FORTH init process
17175 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
17183 CODE MAX \ n1 n2 -- n3 signed maximum
17184 CMP @PSP,TOS \ n2-n1
17185 S< ?GOTO FW1 \ n2<n1
17191 CODE MIN \ n1 n2 -- n3 signed minimum
17192 CMP @PSP,TOS \ n2-n1
17193 S< ?GOTO BW1 \ n2<n1
17199 : U.R \ u n -- display u unsigned in n width (n >= 2)
17201 R> OVER - 0 MAX SPACES TYPE
17205 CODE 20_US \ n -- n * 20 us
17206 BEGIN \ 3 cycles loop + 6~
17207 \ MOV #5,W \ 3 MCLK = 1 MHz
17208 \ MOV #23,W \ 3 MCLK = 4 MHz
17209 MOV #51,W \ 3 MCLK = 8 MHz
17210 \ MOV #104,W \ 3 MCLK = 16 MHz
17211 \ MOV #158,W \ 3 MCLK = 24 MHz
17212 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
17222 CODE TOP_LCD \ LCD Sample
17223 \ \ if write : %xxxxWWWW --
17224 \ \ if read : -- %0000RRRR
17225 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17226 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17227 0= IF \ write LCD bits pattern
17228 AND.B #LCD_DB,TOS \
17229 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17230 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17233 THEN \ read LCD bits pattern
17236 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17237 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17238 AND.B #LCD_DB,TOS \
17243 CODE LCD_W \ byte -- write byte to LCD
17245 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
17246 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
17247 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17248 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17249 COLON \ high level word starts here
17250 TOP_LCD 2 20_US \ write high nibble first
17255 CODE LCD_WrC \ char -- Write Char
17256 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17261 CODE LCD_WrF \ func -- Write Fonction
17262 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17268 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
17273 $02 LCD_WrF 100 20_us
17277 \ : LCD_Entry_set $04 OR LCD_WrF ;
17279 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
17281 \ : LCD_Display_Shift $10 OR LCD_WrF ;
17283 \ : LCD_Fn_Set $20 OR LCD_WrF ;
17285 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
17287 \ : LCD_Goto $80 OR LCD_WrF ;
17289 \ CODE LCD_R \ -- byte read byte from LCD
17290 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17291 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17292 \ COLON \ starts a FORTH word
17293 \ TOP_LCD 2 20_us \ -- %0000HHHH
17294 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
17295 \ HI2LO \ switch from FORTH to assembler
17296 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
17297 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
17298 \ MOV @RSP+,IP \ restore IP saved by COLON
17303 \ CODE LCD_RdS \ -- status Read Status
17304 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17309 \ CODE LCD_RdC \ -- char Read Char
17310 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17315 \ -------------+------+------+------+------++---+---+---+---+---------+
17316 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
17317 \ -------------+------+------+------+------++---+---+---+---+---------+
17318 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
17319 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
17320 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
17321 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
17322 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
17323 \ -------------+------+------+------+------++---+---+---+---+---------+
17326 \ ******************************\
17327 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17328 \ ******************************\
17329 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
17330 \ ------------------------------\
17331 \ define LPM mode for ACCEPT \
17332 \ ------------------------------\
17333 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17334 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17335 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17336 BIT.B #SW2,&SW2_IN \ test switch S2
17337 0= IF \ case of switch S2 pressed
17338 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
17340 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
17343 BIT.B #SW1,&SW1_IN \ test switch S1 input
17344 0= IF \ case of Switch S1 pressed
17345 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
17347 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
17351 RETI \ CPU is ON, GIE is OFF
17356 \ ------------------------------\
17357 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17358 \ ******************************\
17359 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17360 \ ******************************\
17361 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17362 \ \ SMclock = 8|16|24 MHz
17363 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
17364 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
17365 \ \ SR(9)=new Toggle bit memory (ADD on)
17366 \ ------------------------------\
17367 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
17368 \ ------------------------------\
17369 \ define LPM mode for ACCEPT \
17370 \ ------------------------------\
17371 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17372 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17373 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17374 \ ------------------------------\
17375 \ RC5_FirstStartBitHalfCycle: \
17376 \ ------------------------------\
17377 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
17378 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
17379 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
17380 MOV #1778,X \ RC5_Period in us
17381 MOV #14,W \ count of loop
17383 \ ------------------------------\
17384 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
17385 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
17386 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
17387 \ RC5_Compute_3/4_Period: \ |
17388 RRUM #1,X \ X=1/2 cycle |
17392 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
17393 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
17395 \ ------------------------------\
17396 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
17397 \ ------------------------------\
17398 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17399 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
17400 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17401 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17402 SUB #1,W \ decrement count loop
17403 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
17404 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17405 0<> WHILE \ ----> out of loop ----+
17406 \ RC5_compute_7/4_Time_out: \ |
17407 ADD X,Y \ | out of bound = 7/4 period
17408 \ RC5_WaitHalfCycleP1.2_IFG: \ |
17410 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
17411 0>= IF \ | if cycle time out of bound
17412 BIC #$30,&TA0CTL \ | stop timer_A0
17413 RETI \ | then quit to do nothing
17415 \ ------------------------------\ |
17416 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
17418 MOV &TA0R,X \ | | get new RC5_period value
17419 REPEAT \ ----> loop back --+ |
17420 \ ------------------------------\ |
17421 \ RC5_SampleEndOf: \ <---------------------+
17422 \ ------------------------------\
17423 BIC #$30,&TA0CTL \ stop timer_A0
17424 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
17425 \ ******************************\
17426 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17427 \ ******************************\
17428 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
17429 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
17430 XOR IP,X \ (new XOR old) Toggle bit (13)
17431 BIT #BIT13,X \ X(13) = New_RC5_command
17432 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
17434 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
17435 \ ******************************\
17436 \ RC5_ComputeNewRC5word \
17437 \ ******************************\
17439 MOV &BASE,2(PSP) \ save variable BASE before use
17440 MOV TOS,0(PSP) \ save TOS before use
17441 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
17442 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
17443 \ ******************************\
17444 \ RC5_ComputeC6bit \
17445 \ ******************************\
17446 BIT #$4000,IP \ test /C6 bit in IP
17447 0= IF BIS #$40,TOS \ set C6 bit in S
17448 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
17449 \ ******************************\
17450 \ RC5_CommandByteIsDone \ RC5_code --
17451 \ ******************************\
17453 \ ------------------------------\
17454 \ Display IR_RC5 code \
17455 \ ------------------------------\
17456 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
17457 \ ------------------------------\
17458 LO2HI \ switch from assembler to FORTH
17459 ['] LCD_CLEAR IS CR \ redirects CR
17460 ['] LCD_WrC IS EMIT \ redirects EMIT
17461 $10 BASE ! \ change BASE to hexadecimal
17462 CR ." $" 2 U.R \ print IR_RC5 code
17463 ['] (CR) IS CR \ restore CR
17464 ['] (EMIT) IS EMIT \ restore EMIT
17465 HI2LO \ switch from FORTH to assembler
17466 \ ------------------------------\
17467 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
17468 \ ------------------------------\
17469 MOV @PSP+,&BASE \ restore variable BASE
17470 RETI \ CPU is ON, GIE is OFF
17475 \ ------------------------------\
17476 \ TB0CTL = %0000 0010 1001 0100\$3C0
17477 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17478 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17479 \ -- \ID input divider \ 10 = /4
17480 \ -- \MC Mode Control \ 01 = up to TB0CCR0
17481 \ - \TBCLR TimerB Clear
17484 \ --------------------------------\\
17485 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17486 \ -- \CM Capture Mode
17491 \ --- \OUTMOD \ 011 = set/reset
17497 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
17499 \ ------------------------------\
17500 \ set TimerB to make 50kHz PWM \
17501 \ ------------------------------\
17502 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17503 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
17504 \ ------------------------------\
17505 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17506 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
17507 \ ------------------------------\
17508 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17509 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
17510 \ ------------------------------\
17511 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17512 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
17513 \ ------------------------------\
17514 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17515 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
17516 \ ------------------------------\
17517 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
17518 \ ------------------------------\
17519 \ set TimerB to generate PWM for LCD_Vo
17520 \ ------------------------------\
17521 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
17522 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
17523 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17524 \ ------------------------------\
17525 BIS.B #LCDVo,&LCDVo_DIR \
17526 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
17527 \ ------------------------------\
17528 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17529 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17530 \ ------------------------------\
17531 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17532 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17533 \ ------------------------------\
17534 \ WDT interval init part \
17535 \ ------------------------------\
17536 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
17537 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
17538 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
17539 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
17540 \ ------------------------------\
17542 \ ------------------------------\
17543 BIS.B #RC5,&IR_IE \ enable RC5_Int
17544 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17545 \ ------------------------------\
17546 \ init interrupt vectors
17547 \ ------------------------------\
17548 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
17549 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17550 \ ------------------------------\
17551 \ define LPM mode for ACCEPT \
17552 \ ------------------------------\
17553 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17554 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17555 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17557 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
17559 \ ------------------------------\
17561 \ ------------------------------\
17562 $03E8 20_US \ 1- wait 20 ms
17563 $03 TOP_LCD \ 2- send DB5=DB4=1
17564 $CD 20_US \ 3- wait 4,1 ms
17565 $03 TOP_LCD \ 4- send again DB5=DB4=1
17566 $5 20_US \ 5- wait 0,1 ms
17567 $03 TOP_LCD \ 6- send again again DB5=DB4=1
17568 $2 20_US \ wait 40 us = LCD cycle
17569 $02 TOP_LCD \ 7- send DB5=1 DB4=0
17570 $2 20_US \ wait 40 us = LCD cycle
17571 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17572 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17573 LCD_Clear \ 10- "LCD_Clear"
17574 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17575 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17576 LCD_Clear \ 10- "LCD_Clear"
17577 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17578 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17580 ['] (CR) IS CR \ ' (CR) is CR
17581 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
17583 ." RC5toLCD is running. Type STOP to quit"
17584 \ NOECHO \ uncomment to run this app without terminal connexion
17585 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
17586 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
17590 : STOP \ stops multitasking, must to be used before downloading app
17591 ['] (WARM) IS WARM \ remove START app from FORTH init process
17592 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
17600 CODE MAX \ n1 n2 -- n3 signed maximum
17601 CMP @PSP,TOS \ n2-n1
17602 S< ?GOTO FW1 \ n2<n1
17608 CODE MIN \ n1 n2 -- n3 signed minimum
17609 CMP @PSP,TOS \ n2-n1
17610 S< ?GOTO BW1 \ n2<n1
17616 : U.R \ u n -- display u unsigned in n width (n >= 2)
17618 R> OVER - 0 MAX SPACES TYPE
17622 CODE 20_US \ n -- n * 20 us
17623 BEGIN \ 3 cycles loop + 6~
17624 \ MOV #5,W \ 3 MCLK = 1 MHz
17625 \ MOV #23,W \ 3 MCLK = 4 MHz
17626 MOV #51,W \ 3 MCLK = 8 MHz
17627 \ MOV #104,W \ 3 MCLK = 16 MHz
17628 \ MOV #158,W \ 3 MCLK = 24 MHz
17629 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
17639 CODE TOP_LCD \ LCD Sample
17640 \ \ if write : %xxxxWWWW --
17641 \ \ if read : -- %0000RRRR
17642 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17643 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17644 0= IF \ write LCD bits pattern
17645 AND.B #LCD_DB,TOS \
17646 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17647 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17650 THEN \ read LCD bits pattern
17653 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17654 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17655 AND.B #LCD_DB,TOS \
17660 CODE LCD_W \ byte -- write byte to LCD
17662 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
17663 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
17664 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17665 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17666 COLON \ high level word starts here
17667 TOP_LCD 2 20_US \ write high nibble first
17672 CODE LCD_WrC \ char -- Write Char
17673 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17678 CODE LCD_WrF \ func -- Write Fonction
17679 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17685 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
17690 $02 LCD_WrF 100 20_us
17694 \ : LCD_Entry_set $04 OR LCD_WrF ;
17696 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
17698 \ : LCD_Display_Shift $10 OR LCD_WrF ;
17700 \ : LCD_Fn_Set $20 OR LCD_WrF ;
17702 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
17704 \ : LCD_Goto $80 OR LCD_WrF ;
17706 \ CODE LCD_R \ -- byte read byte from LCD
17707 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17708 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17709 \ COLON \ starts a FORTH word
17710 \ TOP_LCD 2 20_us \ -- %0000HHHH
17711 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
17712 \ HI2LO \ switch from FORTH to assembler
17713 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
17714 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
17715 \ MOV @RSP+,IP \ restore IP saved by COLON
17720 \ CODE LCD_RdS \ -- status Read Status
17721 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17726 \ CODE LCD_RdC \ -- char Read Char
17727 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17732 \ -------------+------+------+------+------++---+---+---+---+---------+
17733 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
17734 \ -------------+------+------+------+------++---+---+---+---+---------+
17735 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
17736 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
17737 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
17738 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
17739 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
17740 \ -------------+------+------+------+------++---+---+---+---+---------+
17743 \ ******************************\
17744 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17745 \ ******************************\
17746 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
17747 \ ------------------------------\
17748 \ define LPM mode for ACCEPT \
17749 \ ------------------------------\
17750 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17751 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17752 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17753 BIT.B #SW2,&SW2_IN \ test switch S2
17754 0= IF \ case of switch S2 pressed
17755 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
17757 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
17760 BIT.B #SW1,&SW1_IN \ test switch S1 input
17761 0= IF \ case of Switch S1 pressed
17762 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
17764 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
17768 RETI \ CPU is ON, GIE is OFF
17773 \ ------------------------------\
17774 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17775 \ ******************************\
17776 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17777 \ ******************************\
17778 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17779 \ \ SMclock = 8|16|24 MHz
17780 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
17781 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
17782 \ \ SR(9)=new Toggle bit memory (ADD on)
17783 \ ------------------------------\
17784 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
17785 \ ------------------------------\
17786 \ define LPM mode for ACCEPT \
17787 \ ------------------------------\
17788 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17789 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17790 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17791 \ ------------------------------\
17792 \ RC5_FirstStartBitHalfCycle: \
17793 \ ------------------------------\
17794 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
17795 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
17796 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
17797 MOV #1778,X \ RC5_Period in us
17798 MOV #14,W \ count of loop
17800 \ ------------------------------\
17801 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
17802 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
17803 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
17804 \ RC5_Compute_3/4_Period: \ |
17805 RRUM #1,X \ X=1/2 cycle |
17809 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
17810 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
17812 \ ------------------------------\
17813 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
17814 \ ------------------------------\
17815 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17816 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
17817 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17818 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17819 SUB #1,W \ decrement count loop
17820 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
17821 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17822 0<> WHILE \ ----> out of loop ----+
17823 \ RC5_compute_7/4_Time_out: \ |
17824 ADD X,Y \ | out of bound = 7/4 period
17825 \ RC5_WaitHalfCycleP1.2_IFG: \ |
17827 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
17828 0>= IF \ | if cycle time out of bound
17829 BIC #$30,&TA0CTL \ | stop timer_A0
17830 RETI \ | then quit to do nothing
17832 \ ------------------------------\ |
17833 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
17835 MOV &TA0R,X \ | | get new RC5_period value
17836 REPEAT \ ----> loop back --+ |
17837 \ ------------------------------\ |
17838 \ RC5_SampleEndOf: \ <---------------------+
17839 \ ------------------------------\
17840 BIC #$30,&TA0CTL \ stop timer_A0
17841 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
17842 \ ******************************\
17843 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17844 \ ******************************\
17845 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
17846 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
17847 XOR IP,X \ (new XOR old) Toggle bit (13)
17848 BIT #BIT13,X \ X(13) = New_RC5_command
17849 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
17851 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
17852 \ ******************************\
17853 \ RC5_ComputeNewRC5word \
17854 \ ******************************\
17856 MOV &BASE,2(PSP) \ save variable BASE before use
17857 MOV TOS,0(PSP) \ save TOS before use
17858 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
17859 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
17860 \ ******************************\
17861 \ RC5_ComputeC6bit \
17862 \ ******************************\
17863 BIT #$4000,IP \ test /C6 bit in IP
17864 0= IF BIS #$40,TOS \ set C6 bit in S
17865 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
17866 \ ******************************\
17867 \ RC5_CommandByteIsDone \ RC5_code --
17868 \ ******************************\
17870 \ ------------------------------\
17871 \ Display IR_RC5 code \
17872 \ ------------------------------\
17873 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
17874 \ ------------------------------\
17875 LO2HI \ switch from assembler to FORTH
17876 ['] LCD_CLEAR IS CR \ redirects CR
17877 ['] LCD_WrC IS EMIT \ redirects EMIT
17878 $10 BASE ! \ change BASE to hexadecimal
17879 CR ." $" 2 U.R \ print IR_RC5 code
17880 ['] (CR) IS CR \ restore CR
17881 ['] (EMIT) IS EMIT \ restore EMIT
17882 HI2LO \ switch from FORTH to assembler
17883 \ ------------------------------\
17884 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
17885 \ ------------------------------\
17886 MOV @PSP+,&BASE \ restore variable BASE
17887 RETI \ CPU is ON, GIE is OFF
17892 \ ------------------------------\
17893 \ TB0CTL = %0000 0010 1001 0100\$3C0
17894 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17895 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17896 \ -- \ID input divider \ 10 = /4
17897 \ -- \MC Mode Control \ 01 = up to TB0CCR0
17898 \ - \TBCLR TimerB Clear
17901 \ --------------------------------\\
17902 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17903 \ -- \CM Capture Mode
17908 \ --- \OUTMOD \ 011 = set/reset
17914 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
17916 \ ------------------------------\
17917 \ set TimerB to make 50kHz PWM \
17918 \ ------------------------------\
17919 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17920 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
17921 \ ------------------------------\
17922 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
17923 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
17924 \ ------------------------------\
17925 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17926 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
17927 \ ------------------------------\
17928 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17929 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
17930 \ ------------------------------\
17931 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
17932 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
17933 \ ------------------------------\
17934 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
17935 \ ------------------------------\
17936 \ set TimerB to generate PWM for LCD_Vo
17937 \ ------------------------------\
17938 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
17939 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
17940 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17941 \ ------------------------------\
17942 BIS.B #LCDVo,&LCDVo_DIR \
17943 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
17944 \ ------------------------------\
17945 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17946 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17947 \ ------------------------------\
17948 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17949 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17950 \ ------------------------------\
17951 \ WDT interval init part \
17952 \ ------------------------------\
17953 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
17954 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
17955 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
17956 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
17957 \ ------------------------------\
17959 \ ------------------------------\
17960 BIS.B #RC5,&IR_IE \ enable RC5_Int
17961 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17962 \ ------------------------------\
17963 \ init interrupt vectors
17964 \ ------------------------------\
17965 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
17966 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17967 \ ------------------------------\
17968 \ define LPM mode for ACCEPT \
17969 \ ------------------------------\
17970 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17971 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17972 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17974 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
17976 \ ------------------------------\
17978 \ ------------------------------\
17979 $03E8 20_US \ 1- wait 20 ms
17980 $03 TOP_LCD \ 2- send DB5=DB4=1
17981 $CD 20_US \ 3- wait 4,1 ms
17982 $03 TOP_LCD \ 4- send again DB5=DB4=1
17983 $5 20_US \ 5- wait 0,1 ms
17984 $03 TOP_LCD \ 6- send again again DB5=DB4=1
17985 $2 20_US \ wait 40 us = LCD cycle
17986 $02 TOP_LCD \ 7- send DB5=1 DB4=0
17987 $2 20_US \ wait 40 us = LCD cycle
17988 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17989 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17990 LCD_Clear \ 10- "LCD_Clear"
17991 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17992 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17993 LCD_Clear \ 10- "LCD_Clear"
17994 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17995 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17997 ['] (CR) IS CR \ ' (CR) is CR
17998 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
18000 ." RC5toLCD is running. Type STOP to quit"
18001 \ NOECHO \ uncomment to run this app without terminal connexion
18002 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
18003 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
18007 : STOP \ stops multitasking, must to be used before downloading app
18008 ['] (WARM) IS WARM \ remove START app from FORTH init process
18009 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
18017 CODE MAX \ n1 n2 -- n3 signed maximum
18018 CMP @PSP,TOS \ n2-n1
18019 S< ?GOTO FW1 \ n2<n1
18025 CODE MIN \ n1 n2 -- n3 signed minimum
18026 CMP @PSP,TOS \ n2-n1
18027 S< ?GOTO BW1 \ n2<n1
18033 : U.R \ u n -- display u unsigned in n width (n >= 2)
18035 R> OVER - 0 MAX SPACES TYPE
18039 CODE 20_US \ n -- n * 20 us
18040 BEGIN \ 3 cycles loop + 6~
18041 \ MOV #5,W \ 3 MCLK = 1 MHz
18042 \ MOV #23,W \ 3 MCLK = 4 MHz
18043 MOV #51,W \ 3 MCLK = 8 MHz
18044 \ MOV #104,W \ 3 MCLK = 16 MHz
18045 \ MOV #158,W \ 3 MCLK = 24 MHz
18046 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
18056 CODE TOP_LCD \ LCD Sample
18057 \ \ if write : %xxxxWWWW --
18058 \ \ if read : -- %0000RRRR
18059 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18060 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18061 0= IF \ write LCD bits pattern
18062 AND.B #LCD_DB,TOS \
18063 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18064 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18067 THEN \ read LCD bits pattern
18070 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18071 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18072 AND.B #LCD_DB,TOS \
18077 CODE LCD_W \ byte -- write byte to LCD
18079 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18080 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18081 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18082 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18083 COLON \ high level word starts here
18084 TOP_LCD 2 20_US \ write high nibble first
18089 CODE LCD_WrC \ char -- Write Char
18090 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18095 CODE LCD_WrF \ func -- Write Fonction
18096 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18102 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
18107 $02 LCD_WrF 100 20_us
18111 \ : LCD_Entry_set $04 OR LCD_WrF ;
18113 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
18115 \ : LCD_Display_Shift $10 OR LCD_WrF ;
18117 \ : LCD_Fn_Set $20 OR LCD_WrF ;
18119 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
18121 \ : LCD_Goto $80 OR LCD_WrF ;
18123 \ CODE LCD_R \ -- byte read byte from LCD
18124 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18125 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18126 \ COLON \ starts a FORTH word
18127 \ TOP_LCD 2 20_us \ -- %0000HHHH
18128 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18129 \ HI2LO \ switch from FORTH to assembler
18130 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18131 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18132 \ MOV @RSP+,IP \ restore IP saved by COLON
18137 \ CODE LCD_RdS \ -- status Read Status
18138 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18143 \ CODE LCD_RdC \ -- char Read Char
18144 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18149 \ -------------+------+------+------+------++---+---+---+---+---------+
18150 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
18151 \ -------------+------+------+------+------++---+---+---+---+---------+
18152 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
18153 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
18154 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
18155 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
18156 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
18157 \ -------------+------+------+------+------++---+---+---+---+---------+
18160 \ ******************************\
18161 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18162 \ ******************************\
18163 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
18164 \ ------------------------------\
18165 \ define LPM mode for ACCEPT \
18166 \ ------------------------------\
18167 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18168 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18169 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18170 BIT.B #SW2,&SW2_IN \ test switch S2
18171 0= IF \ case of switch S2 pressed
18172 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
18174 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
18177 BIT.B #SW1,&SW1_IN \ test switch S1 input
18178 0= IF \ case of Switch S1 pressed
18179 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
18181 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
18185 RETI \ CPU is ON, GIE is OFF
18190 \ ------------------------------\
18191 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18192 \ ******************************\
18193 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18194 \ ******************************\
18195 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18196 \ \ SMclock = 8|16|24 MHz
18197 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
18198 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
18199 \ \ SR(9)=new Toggle bit memory (ADD on)
18200 \ ------------------------------\
18201 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
18202 \ ------------------------------\
18203 \ define LPM mode for ACCEPT \
18204 \ ------------------------------\
18205 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18206 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18207 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18208 \ ------------------------------\
18209 \ RC5_FirstStartBitHalfCycle: \
18210 \ ------------------------------\
18211 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
18212 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
18213 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
18214 MOV #1778,X \ RC5_Period in us
18215 MOV #14,W \ count of loop
18217 \ ------------------------------\
18218 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
18219 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
18220 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
18221 \ RC5_Compute_3/4_Period: \ |
18222 RRUM #1,X \ X=1/2 cycle |
18226 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
18227 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
18229 \ ------------------------------\
18230 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
18231 \ ------------------------------\
18232 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18233 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
18234 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18235 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18236 SUB #1,W \ decrement count loop
18237 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
18238 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18239 0<> WHILE \ ----> out of loop ----+
18240 \ RC5_compute_7/4_Time_out: \ |
18241 ADD X,Y \ | out of bound = 7/4 period
18242 \ RC5_WaitHalfCycleP1.2_IFG: \ |
18244 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
18245 0>= IF \ | if cycle time out of bound
18246 BIC #$30,&TA0CTL \ | stop timer_A0
18247 RETI \ | then quit to do nothing
18249 \ ------------------------------\ |
18250 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
18252 MOV &TA0R,X \ | | get new RC5_period value
18253 REPEAT \ ----> loop back --+ |
18254 \ ------------------------------\ |
18255 \ RC5_SampleEndOf: \ <---------------------+
18256 \ ------------------------------\
18257 BIC #$30,&TA0CTL \ stop timer_A0
18258 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
18259 \ ******************************\
18260 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18261 \ ******************************\
18262 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
18263 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
18264 XOR IP,X \ (new XOR old) Toggle bit (13)
18265 BIT #BIT13,X \ X(13) = New_RC5_command
18266 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
18268 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
18269 \ ******************************\
18270 \ RC5_ComputeNewRC5word \
18271 \ ******************************\
18273 MOV &BASE,2(PSP) \ save variable BASE before use
18274 MOV TOS,0(PSP) \ save TOS before use
18275 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
18276 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
18277 \ ******************************\
18278 \ RC5_ComputeC6bit \
18279 \ ******************************\
18280 BIT #$4000,IP \ test /C6 bit in IP
18281 0= IF BIS #$40,TOS \ set C6 bit in S
18282 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
18283 \ ******************************\
18284 \ RC5_CommandByteIsDone \ RC5_code --
18285 \ ******************************\
18287 \ ------------------------------\
18288 \ Display IR_RC5 code \
18289 \ ------------------------------\
18290 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
18291 \ ------------------------------\
18292 LO2HI \ switch from assembler to FORTH
18293 ['] LCD_CLEAR IS CR \ redirects CR
18294 ['] LCD_WrC IS EMIT \ redirects EMIT
18295 $10 BASE ! \ change BASE to hexadecimal
18296 CR ." $" 2 U.R \ print IR_RC5 code
18297 ['] (CR) IS CR \ restore CR
18298 ['] (EMIT) IS EMIT \ restore EMIT
18299 HI2LO \ switch from FORTH to assembler
18300 \ ------------------------------\
18301 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
18302 \ ------------------------------\
18303 MOV @PSP+,&BASE \ restore variable BASE
18304 RETI \ CPU is ON, GIE is OFF
18309 \ ------------------------------\
18310 \ TB0CTL = %0000 0010 1001 0100\$3C0
18311 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18312 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18313 \ -- \ID input divider \ 10 = /4
18314 \ -- \MC Mode Control \ 01 = up to TB0CCR0
18315 \ - \TBCLR TimerB Clear
18318 \ --------------------------------\\
18319 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18320 \ -- \CM Capture Mode
18325 \ --- \OUTMOD \ 011 = set/reset
18331 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
18333 \ ------------------------------\
18334 \ set TimerB to make 50kHz PWM \
18335 \ ------------------------------\
18336 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18337 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
18338 \ ------------------------------\
18339 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18340 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
18341 \ ------------------------------\
18342 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18343 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
18344 \ ------------------------------\
18345 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18346 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
18347 \ ------------------------------\
18348 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18349 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
18350 \ ------------------------------\
18351 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
18352 \ ------------------------------\
18353 \ set TimerB to generate PWM for LCD_Vo
18354 \ ------------------------------\
18355 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
18356 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
18357 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18358 \ ------------------------------\
18359 BIS.B #LCDVo,&LCDVo_DIR \
18360 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
18361 \ ------------------------------\
18362 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18363 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18364 \ ------------------------------\
18365 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18366 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18367 \ ------------------------------\
18368 \ WDT interval init part \
18369 \ ------------------------------\
18370 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
18371 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
18372 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
18373 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
18374 \ ------------------------------\
18376 \ ------------------------------\
18377 BIS.B #RC5,&IR_IE \ enable RC5_Int
18378 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18379 \ ------------------------------\
18380 \ init interrupt vectors
18381 \ ------------------------------\
18382 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
18383 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18384 \ ------------------------------\
18385 \ define LPM mode for ACCEPT \
18386 \ ------------------------------\
18387 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18388 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18389 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18391 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
18393 \ ------------------------------\
18395 \ ------------------------------\
18396 $03E8 20_US \ 1- wait 20 ms
18397 $03 TOP_LCD \ 2- send DB5=DB4=1
18398 $CD 20_US \ 3- wait 4,1 ms
18399 $03 TOP_LCD \ 4- send again DB5=DB4=1
18400 $5 20_US \ 5- wait 0,1 ms
18401 $03 TOP_LCD \ 6- send again again DB5=DB4=1
18402 $2 20_US \ wait 40 us = LCD cycle
18403 $02 TOP_LCD \ 7- send DB5=1 DB4=0
18404 $2 20_US \ wait 40 us = LCD cycle
18405 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18406 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18407 LCD_Clear \ 10- "LCD_Clear"
18408 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18409 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18410 LCD_Clear \ 10- "LCD_Clear"
18411 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18412 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18414 ['] (CR) IS CR \ ' (CR) is CR
18415 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
18417 ." RC5toLCD is running. Type STOP to quit"
18418 \ NOECHO \ uncomment to run this app without terminal connexion
18419 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
18420 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
18424 : STOP \ stops multitasking, must to be used before downloading app
18425 ['] (WARM) IS WARM \ remove START app from FORTH init process
18426 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
18434 CODE MAX \ n1 n2 -- n3 signed maximum
18435 CMP @PSP,TOS \ n2-n1
18436 S< ?GOTO FW1 \ n2<n1
18442 CODE MIN \ n1 n2 -- n3 signed minimum
18443 CMP @PSP,TOS \ n2-n1
18444 S< ?GOTO BW1 \ n2<n1
18450 : U.R \ u n -- display u unsigned in n width (n >= 2)
18452 R> OVER - 0 MAX SPACES TYPE
18456 CODE 20_US \ n -- n * 20 us
18457 BEGIN \ 3 cycles loop + 6~
18458 \ MOV #5,W \ 3 MCLK = 1 MHz
18459 \ MOV #23,W \ 3 MCLK = 4 MHz
18460 MOV #51,W \ 3 MCLK = 8 MHz
18461 \ MOV #104,W \ 3 MCLK = 16 MHz
18462 \ MOV #158,W \ 3 MCLK = 24 MHz
18463 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
18473 CODE TOP_LCD \ LCD Sample
18474 \ \ if write : %xxxxWWWW --
18475 \ \ if read : -- %0000RRRR
18476 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18477 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18478 0= IF \ write LCD bits pattern
18479 AND.B #LCD_DB,TOS \
18480 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18481 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18484 THEN \ read LCD bits pattern
18487 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18488 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18489 AND.B #LCD_DB,TOS \
18494 CODE LCD_W \ byte -- write byte to LCD
18496 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18497 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18498 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18499 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18500 COLON \ high level word starts here
18501 TOP_LCD 2 20_US \ write high nibble first
18506 CODE LCD_WrC \ char -- Write Char
18507 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18512 CODE LCD_WrF \ func -- Write Fonction
18513 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18519 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
18524 $02 LCD_WrF 100 20_us
18528 \ : LCD_Entry_set $04 OR LCD_WrF ;
18530 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
18532 \ : LCD_Display_Shift $10 OR LCD_WrF ;
18534 \ : LCD_Fn_Set $20 OR LCD_WrF ;
18536 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
18538 \ : LCD_Goto $80 OR LCD_WrF ;
18540 \ CODE LCD_R \ -- byte read byte from LCD
18541 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18542 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18543 \ COLON \ starts a FORTH word
18544 \ TOP_LCD 2 20_us \ -- %0000HHHH
18545 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18546 \ HI2LO \ switch from FORTH to assembler
18547 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18548 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18549 \ MOV @RSP+,IP \ restore IP saved by COLON
18554 \ CODE LCD_RdS \ -- status Read Status
18555 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18560 \ CODE LCD_RdC \ -- char Read Char
18561 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18566 \ -------------+------+------+------+------++---+---+---+---+---------+
18567 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
18568 \ -------------+------+------+------+------++---+---+---+---+---------+
18569 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
18570 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
18571 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
18572 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
18573 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
18574 \ -------------+------+------+------+------++---+---+---+---+---------+
18577 \ ******************************\
18578 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18579 \ ******************************\
18580 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
18581 \ ------------------------------\
18582 \ define LPM mode for ACCEPT \
18583 \ ------------------------------\
18584 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18585 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18586 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18587 BIT.B #SW2,&SW2_IN \ test switch S2
18588 0= IF \ case of switch S2 pressed
18589 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
18591 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
18594 BIT.B #SW1,&SW1_IN \ test switch S1 input
18595 0= IF \ case of Switch S1 pressed
18596 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
18598 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
18602 RETI \ CPU is ON, GIE is OFF
18607 \ ------------------------------\
18608 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18609 \ ******************************\
18610 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18611 \ ******************************\
18612 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18613 \ \ SMclock = 8|16|24 MHz
18614 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
18615 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
18616 \ \ SR(9)=new Toggle bit memory (ADD on)
18617 \ ------------------------------\
18618 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
18619 \ ------------------------------\
18620 \ define LPM mode for ACCEPT \
18621 \ ------------------------------\
18622 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18623 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18624 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18625 \ ------------------------------\
18626 \ RC5_FirstStartBitHalfCycle: \
18627 \ ------------------------------\
18628 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
18629 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
18630 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
18631 MOV #1778,X \ RC5_Period in us
18632 MOV #14,W \ count of loop
18634 \ ------------------------------\
18635 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
18636 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
18637 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
18638 \ RC5_Compute_3/4_Period: \ |
18639 RRUM #1,X \ X=1/2 cycle |
18643 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
18644 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
18646 \ ------------------------------\
18647 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
18648 \ ------------------------------\
18649 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18650 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
18651 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18652 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18653 SUB #1,W \ decrement count loop
18654 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
18655 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18656 0<> WHILE \ ----> out of loop ----+
18657 \ RC5_compute_7/4_Time_out: \ |
18658 ADD X,Y \ | out of bound = 7/4 period
18659 \ RC5_WaitHalfCycleP1.2_IFG: \ |
18661 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
18662 0>= IF \ | if cycle time out of bound
18663 BIC #$30,&TA0CTL \ | stop timer_A0
18664 RETI \ | then quit to do nothing
18666 \ ------------------------------\ |
18667 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
18669 MOV &TA0R,X \ | | get new RC5_period value
18670 REPEAT \ ----> loop back --+ |
18671 \ ------------------------------\ |
18672 \ RC5_SampleEndOf: \ <---------------------+
18673 \ ------------------------------\
18674 BIC #$30,&TA0CTL \ stop timer_A0
18675 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
18676 \ ******************************\
18677 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18678 \ ******************************\
18679 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
18680 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
18681 XOR IP,X \ (new XOR old) Toggle bit (13)
18682 BIT #BIT13,X \ X(13) = New_RC5_command
18683 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
18685 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
18686 \ ******************************\
18687 \ RC5_ComputeNewRC5word \
18688 \ ******************************\
18690 MOV &BASE,2(PSP) \ save variable BASE before use
18691 MOV TOS,0(PSP) \ save TOS before use
18692 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
18693 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
18694 \ ******************************\
18695 \ RC5_ComputeC6bit \
18696 \ ******************************\
18697 BIT #$4000,IP \ test /C6 bit in IP
18698 0= IF BIS #$40,TOS \ set C6 bit in S
18699 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
18700 \ ******************************\
18701 \ RC5_CommandByteIsDone \ RC5_code --
18702 \ ******************************\
18704 \ ------------------------------\
18705 \ Display IR_RC5 code \
18706 \ ------------------------------\
18707 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
18708 \ ------------------------------\
18709 LO2HI \ switch from assembler to FORTH
18710 ['] LCD_CLEAR IS CR \ redirects CR
18711 ['] LCD_WrC IS EMIT \ redirects EMIT
18712 $10 BASE ! \ change BASE to hexadecimal
18713 CR ." $" 2 U.R \ print IR_RC5 code
18714 ['] (CR) IS CR \ restore CR
18715 ['] (EMIT) IS EMIT \ restore EMIT
18716 HI2LO \ switch from FORTH to assembler
18717 \ ------------------------------\
18718 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
18719 \ ------------------------------\
18720 MOV @PSP+,&BASE \ restore variable BASE
18721 RETI \ CPU is ON, GIE is OFF
18726 \ ------------------------------\
18727 \ TB0CTL = %0000 0010 1001 0100\$3C0
18728 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18729 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18730 \ -- \ID input divider \ 10 = /4
18731 \ -- \MC Mode Control \ 01 = up to TB0CCR0
18732 \ - \TBCLR TimerB Clear
18735 \ --------------------------------\\
18736 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18737 \ -- \CM Capture Mode
18742 \ --- \OUTMOD \ 011 = set/reset
18748 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
18750 \ ------------------------------\
18751 \ set TimerB to make 50kHz PWM \
18752 \ ------------------------------\
18753 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18754 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
18755 \ ------------------------------\
18756 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
18757 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
18758 \ ------------------------------\
18759 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18760 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
18761 \ ------------------------------\
18762 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18763 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
18764 \ ------------------------------\
18765 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
18766 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
18767 \ ------------------------------\
18768 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
18769 \ ------------------------------\
18770 \ set TimerB to generate PWM for LCD_Vo
18771 \ ------------------------------\
18772 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
18773 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
18774 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18775 \ ------------------------------\
18776 BIS.B #LCDVo,&LCDVo_DIR \
18777 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
18778 \ ------------------------------\
18779 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18780 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18781 \ ------------------------------\
18782 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18783 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18784 \ ------------------------------\
18785 \ WDT interval init part \
18786 \ ------------------------------\
18787 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
18788 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
18789 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
18790 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
18791 \ ------------------------------\
18793 \ ------------------------------\
18794 BIS.B #RC5,&IR_IE \ enable RC5_Int
18795 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18796 \ ------------------------------\
18797 \ init interrupt vectors
18798 \ ------------------------------\
18799 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
18800 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18801 \ ------------------------------\
18802 \ define LPM mode for ACCEPT \
18803 \ ------------------------------\
18804 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18805 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18806 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18808 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
18810 \ ------------------------------\
18812 \ ------------------------------\
18813 $03E8 20_US \ 1- wait 20 ms
18814 $03 TOP_LCD \ 2- send DB5=DB4=1
18815 $CD 20_US \ 3- wait 4,1 ms
18816 $03 TOP_LCD \ 4- send again DB5=DB4=1
18817 $5 20_US \ 5- wait 0,1 ms
18818 $03 TOP_LCD \ 6- send again again DB5=DB4=1
18819 $2 20_US \ wait 40 us = LCD cycle
18820 $02 TOP_LCD \ 7- send DB5=1 DB4=0
18821 $2 20_US \ wait 40 us = LCD cycle
18822 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18823 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18824 LCD_Clear \ 10- "LCD_Clear"
18825 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18826 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18827 LCD_Clear \ 10- "LCD_Clear"
18828 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18829 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18831 ['] (CR) IS CR \ ' (CR) is CR
18832 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
18834 ." RC5toLCD is running. Type STOP to quit"
18835 \ NOECHO \ uncomment to run this app without terminal connexion
18836 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
18837 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
18841 : STOP \ stops multitasking, must to be used before downloading app
18842 ['] (WARM) IS WARM \ remove START app from FORTH init process
18843 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
18851 CODE MAX \ n1 n2 -- n3 signed maximum
18852 CMP @PSP,TOS \ n2-n1
18853 S< ?GOTO FW1 \ n2<n1
18859 CODE MIN \ n1 n2 -- n3 signed minimum
18860 CMP @PSP,TOS \ n2-n1
18861 S< ?GOTO BW1 \ n2<n1
18867 : U.R \ u n -- display u unsigned in n width (n >= 2)
18869 R> OVER - 0 MAX SPACES TYPE
18873 CODE 20_US \ n -- n * 20 us
18874 BEGIN \ 3 cycles loop + 6~
18875 \ MOV #5,W \ 3 MCLK = 1 MHz
18876 \ MOV #23,W \ 3 MCLK = 4 MHz
18877 MOV #51,W \ 3 MCLK = 8 MHz
18878 \ MOV #104,W \ 3 MCLK = 16 MHz
18879 \ MOV #158,W \ 3 MCLK = 24 MHz
18880 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
18890 CODE TOP_LCD \ LCD Sample
18891 \ \ if write : %xxxxWWWW --
18892 \ \ if read : -- %0000RRRR
18893 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18894 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18895 0= IF \ write LCD bits pattern
18896 AND.B #LCD_DB,TOS \
18897 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18898 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18901 THEN \ read LCD bits pattern
18904 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18905 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18906 AND.B #LCD_DB,TOS \
18911 CODE LCD_W \ byte -- write byte to LCD
18913 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
18914 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
18915 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18916 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18917 COLON \ high level word starts here
18918 TOP_LCD 2 20_US \ write high nibble first
18923 CODE LCD_WrC \ char -- Write Char
18924 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18929 CODE LCD_WrF \ func -- Write Fonction
18930 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18936 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
18941 $02 LCD_WrF 100 20_us
18945 \ : LCD_Entry_set $04 OR LCD_WrF ;
18947 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
18949 \ : LCD_Display_Shift $10 OR LCD_WrF ;
18951 \ : LCD_Fn_Set $20 OR LCD_WrF ;
18953 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
18955 \ : LCD_Goto $80 OR LCD_WrF ;
18957 \ CODE LCD_R \ -- byte read byte from LCD
18958 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18959 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18960 \ COLON \ starts a FORTH word
18961 \ TOP_LCD 2 20_us \ -- %0000HHHH
18962 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
18963 \ HI2LO \ switch from FORTH to assembler
18964 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
18965 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
18966 \ MOV @RSP+,IP \ restore IP saved by COLON
18971 \ CODE LCD_RdS \ -- status Read Status
18972 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18977 \ CODE LCD_RdC \ -- char Read Char
18978 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18983 \ -------------+------+------+------+------++---+---+---+---+---------+
18984 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
18985 \ -------------+------+------+------+------++---+---+---+---+---------+
18986 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
18987 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
18988 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
18989 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
18990 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
18991 \ -------------+------+------+------+------++---+---+---+---+---------+
18994 \ ******************************\
18995 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18996 \ ******************************\
18997 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
18998 \ ------------------------------\
18999 \ define LPM mode for ACCEPT \
19000 \ ------------------------------\
19001 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19002 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19003 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19004 BIT.B #SW2,&SW2_IN \ test switch S2
19005 0= IF \ case of switch S2 pressed
19006 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
19008 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
19011 BIT.B #SW1,&SW1_IN \ test switch S1 input
19012 0= IF \ case of Switch S1 pressed
19013 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
19015 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
19019 RETI \ CPU is ON, GIE is OFF
19024 \ ------------------------------\
19025 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19026 \ ******************************\
19027 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19028 \ ******************************\
19029 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19030 \ \ SMclock = 8|16|24 MHz
19031 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
19032 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
19033 \ \ SR(9)=new Toggle bit memory (ADD on)
19034 \ ------------------------------\
19035 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
19036 \ ------------------------------\
19037 \ define LPM mode for ACCEPT \
19038 \ ------------------------------\
19039 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19040 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19041 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19042 \ ------------------------------\
19043 \ RC5_FirstStartBitHalfCycle: \
19044 \ ------------------------------\
19045 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
19046 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
19047 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
19048 MOV #1778,X \ RC5_Period in us
19049 MOV #14,W \ count of loop
19051 \ ------------------------------\
19052 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
19053 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
19054 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
19055 \ RC5_Compute_3/4_Period: \ |
19056 RRUM #1,X \ X=1/2 cycle |
19060 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
19061 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
19063 \ ------------------------------\
19064 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
19065 \ ------------------------------\
19066 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19067 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
19068 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19069 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19070 SUB #1,W \ decrement count loop
19071 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
19072 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19073 0<> WHILE \ ----> out of loop ----+
19074 \ RC5_compute_7/4_Time_out: \ |
19075 ADD X,Y \ | out of bound = 7/4 period
19076 \ RC5_WaitHalfCycleP1.2_IFG: \ |
19078 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
19079 0>= IF \ | if cycle time out of bound
19080 BIC #$30,&TA0CTL \ | stop timer_A0
19081 RETI \ | then quit to do nothing
19083 \ ------------------------------\ |
19084 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
19086 MOV &TA0R,X \ | | get new RC5_period value
19087 REPEAT \ ----> loop back --+ |
19088 \ ------------------------------\ |
19089 \ RC5_SampleEndOf: \ <---------------------+
19090 \ ------------------------------\
19091 BIC #$30,&TA0CTL \ stop timer_A0
19092 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
19093 \ ******************************\
19094 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19095 \ ******************************\
19096 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
19097 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
19098 XOR IP,X \ (new XOR old) Toggle bit (13)
19099 BIT #BIT13,X \ X(13) = New_RC5_command
19100 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
19102 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
19103 \ ******************************\
19104 \ RC5_ComputeNewRC5word \
19105 \ ******************************\
19107 MOV &BASE,2(PSP) \ save variable BASE before use
19108 MOV TOS,0(PSP) \ save TOS before use
19109 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
19110 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
19111 \ ******************************\
19112 \ RC5_ComputeC6bit \
19113 \ ******************************\
19114 BIT #$4000,IP \ test /C6 bit in IP
19115 0= IF BIS #$40,TOS \ set C6 bit in S
19116 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
19117 \ ******************************\
19118 \ RC5_CommandByteIsDone \ RC5_code --
19119 \ ******************************\
19121 \ ------------------------------\
19122 \ Display IR_RC5 code \
19123 \ ------------------------------\
19124 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
19125 \ ------------------------------\
19126 LO2HI \ switch from assembler to FORTH
19127 ['] LCD_CLEAR IS CR \ redirects CR
19128 ['] LCD_WrC IS EMIT \ redirects EMIT
19129 $10 BASE ! \ change BASE to hexadecimal
19130 CR ." $" 2 U.R \ print IR_RC5 code
19131 ['] (CR) IS CR \ restore CR
19132 ['] (EMIT) IS EMIT \ restore EMIT
19133 HI2LO \ switch from FORTH to assembler
19134 \ ------------------------------\
19135 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
19136 \ ------------------------------\
19137 MOV @PSP+,&BASE \ restore variable BASE
19138 RETI \ CPU is ON, GIE is OFF
19143 \ ------------------------------\
19144 \ TB0CTL = %0000 0010 1001 0100\$3C0
19145 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19146 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19147 \ -- \ID input divider \ 10 = /4
19148 \ -- \MC Mode Control \ 01 = up to TB0CCR0
19149 \ - \TBCLR TimerB Clear
19152 \ --------------------------------\\
19153 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19154 \ -- \CM Capture Mode
19159 \ --- \OUTMOD \ 011 = set/reset
19165 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
19167 \ ------------------------------\
19168 \ set TimerB to make 50kHz PWM \
19169 \ ------------------------------\
19170 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19171 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
19172 \ ------------------------------\
19173 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19174 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
19175 \ ------------------------------\
19176 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19177 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
19178 \ ------------------------------\
19179 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19180 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
19181 \ ------------------------------\
19182 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19183 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
19184 \ ------------------------------\
19185 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
19186 \ ------------------------------\
19187 \ set TimerB to generate PWM for LCD_Vo
19188 \ ------------------------------\
19189 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
19190 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
19191 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19192 \ ------------------------------\
19193 BIS.B #LCDVo,&LCDVo_DIR \
19194 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
19195 \ ------------------------------\
19196 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19197 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19198 \ ------------------------------\
19199 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19200 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19201 \ ------------------------------\
19202 \ WDT interval init part \
19203 \ ------------------------------\
19204 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
19205 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
19206 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
19207 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
19208 \ ------------------------------\
19210 \ ------------------------------\
19211 BIS.B #RC5,&IR_IE \ enable RC5_Int
19212 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19213 \ ------------------------------\
19214 \ init interrupt vectors
19215 \ ------------------------------\
19216 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
19217 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19218 \ ------------------------------\
19219 \ define LPM mode for ACCEPT \
19220 \ ------------------------------\
19221 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19222 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19223 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19225 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
19227 \ ------------------------------\
19229 \ ------------------------------\
19230 $03E8 20_US \ 1- wait 20 ms
19231 $03 TOP_LCD \ 2- send DB5=DB4=1
19232 $CD 20_US \ 3- wait 4,1 ms
19233 $03 TOP_LCD \ 4- send again DB5=DB4=1
19234 $5 20_US \ 5- wait 0,1 ms
19235 $03 TOP_LCD \ 6- send again again DB5=DB4=1
19236 $2 20_US \ wait 40 us = LCD cycle
19237 $02 TOP_LCD \ 7- send DB5=1 DB4=0
19238 $2 20_US \ wait 40 us = LCD cycle
19239 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19240 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19241 LCD_Clear \ 10- "LCD_Clear"
19242 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19243 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19244 LCD_Clear \ 10- "LCD_Clear"
19245 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19246 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19248 ['] (CR) IS CR \ ' (CR) is CR
19249 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
19251 ." RC5toLCD is running. Type STOP to quit"
19252 \ NOECHO \ uncomment to run this app without terminal connexion
19253 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
19254 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
19258 : STOP \ stops multitasking, must to be used before downloading app
19259 ['] (WARM) IS WARM \ remove START app from FORTH init process
19260 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
19268 CODE MAX \ n1 n2 -- n3 signed maximum
19269 CMP @PSP,TOS \ n2-n1
19270 S< ?GOTO FW1 \ n2<n1
19276 CODE MIN \ n1 n2 -- n3 signed minimum
19277 CMP @PSP,TOS \ n2-n1
19278 S< ?GOTO BW1 \ n2<n1
19284 : U.R \ u n -- display u unsigned in n width (n >= 2)
19286 R> OVER - 0 MAX SPACES TYPE
19290 CODE 20_US \ n -- n * 20 us
19291 BEGIN \ 3 cycles loop + 6~
19292 \ MOV #5,W \ 3 MCLK = 1 MHz
19293 \ MOV #23,W \ 3 MCLK = 4 MHz
19294 MOV #51,W \ 3 MCLK = 8 MHz
19295 \ MOV #104,W \ 3 MCLK = 16 MHz
19296 \ MOV #158,W \ 3 MCLK = 24 MHz
19297 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
19307 CODE TOP_LCD \ LCD Sample
19308 \ \ if write : %xxxxWWWW --
19309 \ \ if read : -- %0000RRRR
19310 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19311 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19312 0= IF \ write LCD bits pattern
19313 AND.B #LCD_DB,TOS \
19314 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19315 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19318 THEN \ read LCD bits pattern
19321 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19322 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19323 AND.B #LCD_DB,TOS \
19328 CODE LCD_W \ byte -- write byte to LCD
19330 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
19331 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
19332 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19333 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19334 COLON \ high level word starts here
19335 TOP_LCD 2 20_US \ write high nibble first
19340 CODE LCD_WrC \ char -- Write Char
19341 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19346 CODE LCD_WrF \ func -- Write Fonction
19347 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19353 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
19358 $02 LCD_WrF 100 20_us
19362 \ : LCD_Entry_set $04 OR LCD_WrF ;
19364 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
19366 \ : LCD_Display_Shift $10 OR LCD_WrF ;
19368 \ : LCD_Fn_Set $20 OR LCD_WrF ;
19370 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
19372 \ : LCD_Goto $80 OR LCD_WrF ;
19374 \ CODE LCD_R \ -- byte read byte from LCD
19375 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19376 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19377 \ COLON \ starts a FORTH word
19378 \ TOP_LCD 2 20_us \ -- %0000HHHH
19379 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
19380 \ HI2LO \ switch from FORTH to assembler
19381 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
19382 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
19383 \ MOV @RSP+,IP \ restore IP saved by COLON
19388 \ CODE LCD_RdS \ -- status Read Status
19389 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19394 \ CODE LCD_RdC \ -- char Read Char
19395 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19400 \ -------------+------+------+------+------++---+---+---+---+---------+
19401 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
19402 \ -------------+------+------+------+------++---+---+---+---+---------+
19403 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
19404 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
19405 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
19406 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
19407 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
19408 \ -------------+------+------+------+------++---+---+---+---+---------+
19411 \ ******************************\
19412 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19413 \ ******************************\
19414 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
19415 \ ------------------------------\
19416 \ define LPM mode for ACCEPT \
19417 \ ------------------------------\
19418 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19419 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19420 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19421 BIT.B #SW2,&SW2_IN \ test switch S2
19422 0= IF \ case of switch S2 pressed
19423 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
19425 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
19428 BIT.B #SW1,&SW1_IN \ test switch S1 input
19429 0= IF \ case of Switch S1 pressed
19430 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
19432 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
19436 RETI \ CPU is ON, GIE is OFF
19441 \ ------------------------------\
19442 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19443 \ ******************************\
19444 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19445 \ ******************************\
19446 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19447 \ \ SMclock = 8|16|24 MHz
19448 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
19449 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
19450 \ \ SR(9)=new Toggle bit memory (ADD on)
19451 \ ------------------------------\
19452 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
19453 \ ------------------------------\
19454 \ define LPM mode for ACCEPT \
19455 \ ------------------------------\
19456 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19457 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19458 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19459 \ ------------------------------\
19460 \ RC5_FirstStartBitHalfCycle: \
19461 \ ------------------------------\
19462 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
19463 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
19464 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
19465 MOV #1778,X \ RC5_Period in us
19466 MOV #14,W \ count of loop
19468 \ ------------------------------\
19469 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
19470 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
19471 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
19472 \ RC5_Compute_3/4_Period: \ |
19473 RRUM #1,X \ X=1/2 cycle |
19477 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
19478 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
19480 \ ------------------------------\
19481 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
19482 \ ------------------------------\
19483 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19484 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
19485 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19486 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19487 SUB #1,W \ decrement count loop
19488 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
19489 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19490 0<> WHILE \ ----> out of loop ----+
19491 \ RC5_compute_7/4_Time_out: \ |
19492 ADD X,Y \ | out of bound = 7/4 period
19493 \ RC5_WaitHalfCycleP1.2_IFG: \ |
19495 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
19496 0>= IF \ | if cycle time out of bound
19497 BIC #$30,&TA0CTL \ | stop timer_A0
19498 RETI \ | then quit to do nothing
19500 \ ------------------------------\ |
19501 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
19503 MOV &TA0R,X \ | | get new RC5_period value
19504 REPEAT \ ----> loop back --+ |
19505 \ ------------------------------\ |
19506 \ RC5_SampleEndOf: \ <---------------------+
19507 \ ------------------------------\
19508 BIC #$30,&TA0CTL \ stop timer_A0
19509 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
19510 \ ******************************\
19511 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19512 \ ******************************\
19513 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
19514 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
19515 XOR IP,X \ (new XOR old) Toggle bit (13)
19516 BIT #BIT13,X \ X(13) = New_RC5_command
19517 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
19519 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
19520 \ ******************************\
19521 \ RC5_ComputeNewRC5word \
19522 \ ******************************\
19524 MOV &BASE,2(PSP) \ save variable BASE before use
19525 MOV TOS,0(PSP) \ save TOS before use
19526 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
19527 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
19528 \ ******************************\
19529 \ RC5_ComputeC6bit \
19530 \ ******************************\
19531 BIT #$4000,IP \ test /C6 bit in IP
19532 0= IF BIS #$40,TOS \ set C6 bit in S
19533 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
19534 \ ******************************\
19535 \ RC5_CommandByteIsDone \ RC5_code --
19536 \ ******************************\
19538 \ ------------------------------\
19539 \ Display IR_RC5 code \
19540 \ ------------------------------\
19541 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
19542 \ ------------------------------\
19543 LO2HI \ switch from assembler to FORTH
19544 ['] LCD_CLEAR IS CR \ redirects CR
19545 ['] LCD_WrC IS EMIT \ redirects EMIT
19546 $10 BASE ! \ change BASE to hexadecimal
19547 CR ." $" 2 U.R \ print IR_RC5 code
19548 ['] (CR) IS CR \ restore CR
19549 ['] (EMIT) IS EMIT \ restore EMIT
19550 HI2LO \ switch from FORTH to assembler
19551 \ ------------------------------\
19552 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
19553 \ ------------------------------\
19554 MOV @PSP+,&BASE \ restore variable BASE
19555 RETI \ CPU is ON, GIE is OFF
19560 \ ------------------------------\
19561 \ TB0CTL = %0000 0010 1001 0100\$3C0
19562 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19563 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19564 \ -- \ID input divider \ 10 = /4
19565 \ -- \MC Mode Control \ 01 = up to TB0CCR0
19566 \ - \TBCLR TimerB Clear
19569 \ --------------------------------\\
19570 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19571 \ -- \CM Capture Mode
19576 \ --- \OUTMOD \ 011 = set/reset
19582 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
19584 \ ------------------------------\
19585 \ set TimerB to make 50kHz PWM \
19586 \ ------------------------------\
19587 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19588 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
19589 \ ------------------------------\
19590 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
19591 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
19592 \ ------------------------------\
19593 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19594 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
19595 \ ------------------------------\
19596 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19597 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
19598 \ ------------------------------\
19599 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
19600 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
19601 \ ------------------------------\
19602 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
19603 \ ------------------------------\
19604 \ set TimerB to generate PWM for LCD_Vo
19605 \ ------------------------------\
19606 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
19607 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
19608 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19609 \ ------------------------------\
19610 BIS.B #LCDVo,&LCDVo_DIR \
19611 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
19612 \ ------------------------------\
19613 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19614 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19615 \ ------------------------------\
19616 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19617 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19618 \ ------------------------------\
19619 \ WDT interval init part \
19620 \ ------------------------------\
19621 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
19622 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
19623 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
19624 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
19625 \ ------------------------------\
19627 \ ------------------------------\
19628 BIS.B #RC5,&IR_IE \ enable RC5_Int
19629 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19630 \ ------------------------------\
19631 \ init interrupt vectors
19632 \ ------------------------------\
19633 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
19634 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19635 \ ------------------------------\
19636 \ define LPM mode for ACCEPT \
19637 \ ------------------------------\
19638 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19639 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19640 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19642 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
19644 \ ------------------------------\
19646 \ ------------------------------\
19647 $03E8 20_US \ 1- wait 20 ms
19648 $03 TOP_LCD \ 2- send DB5=DB4=1
19649 $CD 20_US \ 3- wait 4,1 ms
19650 $03 TOP_LCD \ 4- send again DB5=DB4=1
19651 $5 20_US \ 5- wait 0,1 ms
19652 $03 TOP_LCD \ 6- send again again DB5=DB4=1
19653 $2 20_US \ wait 40 us = LCD cycle
19654 $02 TOP_LCD \ 7- send DB5=1 DB4=0
19655 $2 20_US \ wait 40 us = LCD cycle
19656 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19657 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19658 LCD_Clear \ 10- "LCD_Clear"
19659 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19660 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19661 LCD_Clear \ 10- "LCD_Clear"
19662 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19663 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19665 ['] (CR) IS CR \ ' (CR) is CR
19666 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
19668 ." RC5toLCD is running. Type STOP to quit"
19669 \ NOECHO \ uncomment to run this app without terminal connexion
19670 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
19671 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
19675 : STOP \ stops multitasking, must to be used before downloading app
19676 ['] (WARM) IS WARM \ remove START app from FORTH init process
19677 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
19685 CODE MAX \ n1 n2 -- n3 signed maximum
19686 CMP @PSP,TOS \ n2-n1
19687 S< ?GOTO FW1 \ n2<n1
19693 CODE MIN \ n1 n2 -- n3 signed minimum
19694 CMP @PSP,TOS \ n2-n1
19695 S< ?GOTO BW1 \ n2<n1
19701 : U.R \ u n -- display u unsigned in n width (n >= 2)
19703 R> OVER - 0 MAX SPACES TYPE
19707 CODE 20_US \ n -- n * 20 us
19708 BEGIN \ 3 cycles loop + 6~
19709 \ MOV #5,W \ 3 MCLK = 1 MHz
19710 \ MOV #23,W \ 3 MCLK = 4 MHz
19711 MOV #51,W \ 3 MCLK = 8 MHz
19712 \ MOV #104,W \ 3 MCLK = 16 MHz
19713 \ MOV #158,W \ 3 MCLK = 24 MHz
19714 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
19724 CODE TOP_LCD \ LCD Sample
19725 \ \ if write : %xxxxWWWW --
19726 \ \ if read : -- %0000RRRR
19727 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19728 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19729 0= IF \ write LCD bits pattern
19730 AND.B #LCD_DB,TOS \
19731 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19732 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19735 THEN \ read LCD bits pattern
19738 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19739 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19740 AND.B #LCD_DB,TOS \
19745 CODE LCD_W \ byte -- write byte to LCD
19747 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
19748 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
19749 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19750 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19751 COLON \ high level word starts here
19752 TOP_LCD 2 20_US \ write high nibble first
19757 CODE LCD_WrC \ char -- Write Char
19758 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19763 CODE LCD_WrF \ func -- Write Fonction
19764 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19770 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
19775 $02 LCD_WrF 100 20_us
19779 \ : LCD_Entry_set $04 OR LCD_WrF ;
19781 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
19783 \ : LCD_Display_Shift $10 OR LCD_WrF ;
19785 \ : LCD_Fn_Set $20 OR LCD_WrF ;
19787 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
19789 \ : LCD_Goto $80 OR LCD_WrF ;
19791 \ CODE LCD_R \ -- byte read byte from LCD
19792 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19793 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19794 \ COLON \ starts a FORTH word
19795 \ TOP_LCD 2 20_us \ -- %0000HHHH
19796 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
19797 \ HI2LO \ switch from FORTH to assembler
19798 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
19799 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
19800 \ MOV @RSP+,IP \ restore IP saved by COLON
19805 \ CODE LCD_RdS \ -- status Read Status
19806 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19811 \ CODE LCD_RdC \ -- char Read Char
19812 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19817 \ -------------+------+------+------+------++---+---+---+---+---------+
19818 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
19819 \ -------------+------+------+------+------++---+---+---+---+---------+
19820 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
19821 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
19822 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
19823 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
19824 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
19825 \ -------------+------+------+------+------++---+---+---+---+---------+
19828 \ ******************************\
19829 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19830 \ ******************************\
19831 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
19832 \ ------------------------------\
19833 \ define LPM mode for ACCEPT \
19834 \ ------------------------------\
19835 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19836 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19837 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19838 BIT.B #SW2,&SW2_IN \ test switch S2
19839 0= IF \ case of switch S2 pressed
19840 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
19842 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
19845 BIT.B #SW1,&SW1_IN \ test switch S1 input
19846 0= IF \ case of Switch S1 pressed
19847 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
19849 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
19853 RETI \ CPU is ON, GIE is OFF
19858 \ ------------------------------\
19859 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19860 \ ******************************\
19861 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19862 \ ******************************\
19863 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19864 \ \ SMclock = 8|16|24 MHz
19865 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
19866 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
19867 \ \ SR(9)=new Toggle bit memory (ADD on)
19868 \ ------------------------------\
19869 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
19870 \ ------------------------------\
19871 \ define LPM mode for ACCEPT \
19872 \ ------------------------------\
19873 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19874 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19875 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19876 \ ------------------------------\
19877 \ RC5_FirstStartBitHalfCycle: \
19878 \ ------------------------------\
19879 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
19880 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
19881 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
19882 MOV #1778,X \ RC5_Period in us
19883 MOV #14,W \ count of loop
19885 \ ------------------------------\
19886 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
19887 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
19888 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
19889 \ RC5_Compute_3/4_Period: \ |
19890 RRUM #1,X \ X=1/2 cycle |
19894 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
19895 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
19897 \ ------------------------------\
19898 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
19899 \ ------------------------------\
19900 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19901 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
19902 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19903 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19904 SUB #1,W \ decrement count loop
19905 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
19906 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19907 0<> WHILE \ ----> out of loop ----+
19908 \ RC5_compute_7/4_Time_out: \ |
19909 ADD X,Y \ | out of bound = 7/4 period
19910 \ RC5_WaitHalfCycleP1.2_IFG: \ |
19912 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
19913 0>= IF \ | if cycle time out of bound
19914 BIC #$30,&TA0CTL \ | stop timer_A0
19915 RETI \ | then quit to do nothing
19917 \ ------------------------------\ |
19918 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
19920 MOV &TA0R,X \ | | get new RC5_period value
19921 REPEAT \ ----> loop back --+ |
19922 \ ------------------------------\ |
19923 \ RC5_SampleEndOf: \ <---------------------+
19924 \ ------------------------------\
19925 BIC #$30,&TA0CTL \ stop timer_A0
19926 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
19927 \ ******************************\
19928 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19929 \ ******************************\
19930 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
19931 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
19932 XOR IP,X \ (new XOR old) Toggle bit (13)
19933 BIT #BIT13,X \ X(13) = New_RC5_command
19934 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
19936 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
19937 \ ******************************\
19938 \ RC5_ComputeNewRC5word \
19939 \ ******************************\
19941 MOV &BASE,2(PSP) \ save variable BASE before use
19942 MOV TOS,0(PSP) \ save TOS before use
19943 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
19944 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
19945 \ ******************************\
19946 \ RC5_ComputeC6bit \
19947 \ ******************************\
19948 BIT #$4000,IP \ test /C6 bit in IP
19949 0= IF BIS #$40,TOS \ set C6 bit in S
19950 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
19951 \ ******************************\
19952 \ RC5_CommandByteIsDone \ RC5_code --
19953 \ ******************************\
19955 \ ------------------------------\
19956 \ Display IR_RC5 code \
19957 \ ------------------------------\
19958 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
19959 \ ------------------------------\
19960 LO2HI \ switch from assembler to FORTH
19961 ['] LCD_CLEAR IS CR \ redirects CR
19962 ['] LCD_WrC IS EMIT \ redirects EMIT
19963 $10 BASE ! \ change BASE to hexadecimal
19964 CR ." $" 2 U.R \ print IR_RC5 code
19965 ['] (CR) IS CR \ restore CR
19966 ['] (EMIT) IS EMIT \ restore EMIT
19967 HI2LO \ switch from FORTH to assembler
19968 \ ------------------------------\
19969 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
19970 \ ------------------------------\
19971 MOV @PSP+,&BASE \ restore variable BASE
19972 RETI \ CPU is ON, GIE is OFF
19977 \ ------------------------------\
19978 \ TB0CTL = %0000 0010 1001 0100\$3C0
19979 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19980 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19981 \ -- \ID input divider \ 10 = /4
19982 \ -- \MC Mode Control \ 01 = up to TB0CCR0
19983 \ - \TBCLR TimerB Clear
19986 \ --------------------------------\\
19987 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19988 \ -- \CM Capture Mode
19993 \ --- \OUTMOD \ 011 = set/reset
19999 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
20001 \ ------------------------------\
20002 \ set TimerB to make 50kHz PWM \
20003 \ ------------------------------\
20004 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20005 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
20006 \ ------------------------------\
20007 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20008 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
20009 \ ------------------------------\
20010 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20011 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
20012 \ ------------------------------\
20013 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20014 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
20015 \ ------------------------------\
20016 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20017 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
20018 \ ------------------------------\
20019 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
20020 \ ------------------------------\
20021 \ set TimerB to generate PWM for LCD_Vo
20022 \ ------------------------------\
20023 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
20024 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
20025 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20026 \ ------------------------------\
20027 BIS.B #LCDVo,&LCDVo_DIR \
20028 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
20029 \ ------------------------------\
20030 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20031 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20032 \ ------------------------------\
20033 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20034 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20035 \ ------------------------------\
20036 \ WDT interval init part \
20037 \ ------------------------------\
20038 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
20039 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
20040 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
20041 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
20042 \ ------------------------------\
20044 \ ------------------------------\
20045 BIS.B #RC5,&IR_IE \ enable RC5_Int
20046 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20047 \ ------------------------------\
20048 \ init interrupt vectors
20049 \ ------------------------------\
20050 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
20051 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20052 \ ------------------------------\
20053 \ define LPM mode for ACCEPT \
20054 \ ------------------------------\
20055 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20056 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20057 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20059 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
20061 \ ------------------------------\
20063 \ ------------------------------\
20064 $03E8 20_US \ 1- wait 20 ms
20065 $03 TOP_LCD \ 2- send DB5=DB4=1
20066 $CD 20_US \ 3- wait 4,1 ms
20067 $03 TOP_LCD \ 4- send again DB5=DB4=1
20068 $5 20_US \ 5- wait 0,1 ms
20069 $03 TOP_LCD \ 6- send again again DB5=DB4=1
20070 $2 20_US \ wait 40 us = LCD cycle
20071 $02 TOP_LCD \ 7- send DB5=1 DB4=0
20072 $2 20_US \ wait 40 us = LCD cycle
20073 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20074 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20075 LCD_Clear \ 10- "LCD_Clear"
20076 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20077 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20078 LCD_Clear \ 10- "LCD_Clear"
20079 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20080 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20082 ['] (CR) IS CR \ ' (CR) is CR
20083 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
20085 ." RC5toLCD is running. Type STOP to quit"
20086 \ NOECHO \ uncomment to run this app without terminal connexion
20087 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
20088 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
20092 : STOP \ stops multitasking, must to be used before downloading app
20093 ['] (WARM) IS WARM \ remove START app from FORTH init process
20094 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
20102 CODE MAX \ n1 n2 -- n3 signed maximum
20103 CMP @PSP,TOS \ n2-n1
20104 S< ?GOTO FW1 \ n2<n1
20110 CODE MIN \ n1 n2 -- n3 signed minimum
20111 CMP @PSP,TOS \ n2-n1
20112 S< ?GOTO BW1 \ n2<n1
20118 : U.R \ u n -- display u unsigned in n width (n >= 2)
20120 R> OVER - 0 MAX SPACES TYPE
20124 CODE 20_US \ n -- n * 20 us
20125 BEGIN \ 3 cycles loop + 6~
20126 \ MOV #5,W \ 3 MCLK = 1 MHz
20127 \ MOV #23,W \ 3 MCLK = 4 MHz
20128 MOV #51,W \ 3 MCLK = 8 MHz
20129 \ MOV #104,W \ 3 MCLK = 16 MHz
20130 \ MOV #158,W \ 3 MCLK = 24 MHz
20131 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
20141 CODE TOP_LCD \ LCD Sample
20142 \ \ if write : %xxxxWWWW --
20143 \ \ if read : -- %0000RRRR
20144 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20145 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20146 0= IF \ write LCD bits pattern
20147 AND.B #LCD_DB,TOS \
20148 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20149 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20152 THEN \ read LCD bits pattern
20155 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20156 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20157 AND.B #LCD_DB,TOS \
20162 CODE LCD_W \ byte -- write byte to LCD
20164 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20165 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20166 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20167 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20168 COLON \ high level word starts here
20169 TOP_LCD 2 20_US \ write high nibble first
20174 CODE LCD_WrC \ char -- Write Char
20175 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20180 CODE LCD_WrF \ func -- Write Fonction
20181 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20187 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
20192 $02 LCD_WrF 100 20_us
20196 \ : LCD_Entry_set $04 OR LCD_WrF ;
20198 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
20200 \ : LCD_Display_Shift $10 OR LCD_WrF ;
20202 \ : LCD_Fn_Set $20 OR LCD_WrF ;
20204 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
20206 \ : LCD_Goto $80 OR LCD_WrF ;
20208 \ CODE LCD_R \ -- byte read byte from LCD
20209 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20210 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20211 \ COLON \ starts a FORTH word
20212 \ TOP_LCD 2 20_us \ -- %0000HHHH
20213 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20214 \ HI2LO \ switch from FORTH to assembler
20215 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20216 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20217 \ MOV @RSP+,IP \ restore IP saved by COLON
20222 \ CODE LCD_RdS \ -- status Read Status
20223 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20228 \ CODE LCD_RdC \ -- char Read Char
20229 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20234 \ -------------+------+------+------+------++---+---+---+---+---------+
20235 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
20236 \ -------------+------+------+------+------++---+---+---+---+---------+
20237 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
20238 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
20239 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
20240 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
20241 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
20242 \ -------------+------+------+------+------++---+---+---+---+---------+
20245 \ ******************************\
20246 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20247 \ ******************************\
20248 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
20249 \ ------------------------------\
20250 \ define LPM mode for ACCEPT \
20251 \ ------------------------------\
20252 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20253 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20254 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20255 BIT.B #SW2,&SW2_IN \ test switch S2
20256 0= IF \ case of switch S2 pressed
20257 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
20259 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
20262 BIT.B #SW1,&SW1_IN \ test switch S1 input
20263 0= IF \ case of Switch S1 pressed
20264 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
20266 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
20270 RETI \ CPU is ON, GIE is OFF
20275 \ ------------------------------\
20276 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20277 \ ******************************\
20278 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20279 \ ******************************\
20280 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20281 \ \ SMclock = 8|16|24 MHz
20282 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
20283 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
20284 \ \ SR(9)=new Toggle bit memory (ADD on)
20285 \ ------------------------------\
20286 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
20287 \ ------------------------------\
20288 \ define LPM mode for ACCEPT \
20289 \ ------------------------------\
20290 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20291 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20292 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20293 \ ------------------------------\
20294 \ RC5_FirstStartBitHalfCycle: \
20295 \ ------------------------------\
20296 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
20297 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
20298 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
20299 MOV #1778,X \ RC5_Period in us
20300 MOV #14,W \ count of loop
20302 \ ------------------------------\
20303 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
20304 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
20305 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
20306 \ RC5_Compute_3/4_Period: \ |
20307 RRUM #1,X \ X=1/2 cycle |
20311 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
20312 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
20314 \ ------------------------------\
20315 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
20316 \ ------------------------------\
20317 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20318 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
20319 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20320 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20321 SUB #1,W \ decrement count loop
20322 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
20323 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20324 0<> WHILE \ ----> out of loop ----+
20325 \ RC5_compute_7/4_Time_out: \ |
20326 ADD X,Y \ | out of bound = 7/4 period
20327 \ RC5_WaitHalfCycleP1.2_IFG: \ |
20329 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
20330 0>= IF \ | if cycle time out of bound
20331 BIC #$30,&TA0CTL \ | stop timer_A0
20332 RETI \ | then quit to do nothing
20334 \ ------------------------------\ |
20335 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
20337 MOV &TA0R,X \ | | get new RC5_period value
20338 REPEAT \ ----> loop back --+ |
20339 \ ------------------------------\ |
20340 \ RC5_SampleEndOf: \ <---------------------+
20341 \ ------------------------------\
20342 BIC #$30,&TA0CTL \ stop timer_A0
20343 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
20344 \ ******************************\
20345 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20346 \ ******************************\
20347 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
20348 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
20349 XOR IP,X \ (new XOR old) Toggle bit (13)
20350 BIT #BIT13,X \ X(13) = New_RC5_command
20351 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
20353 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
20354 \ ******************************\
20355 \ RC5_ComputeNewRC5word \
20356 \ ******************************\
20358 MOV &BASE,2(PSP) \ save variable BASE before use
20359 MOV TOS,0(PSP) \ save TOS before use
20360 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
20361 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
20362 \ ******************************\
20363 \ RC5_ComputeC6bit \
20364 \ ******************************\
20365 BIT #$4000,IP \ test /C6 bit in IP
20366 0= IF BIS #$40,TOS \ set C6 bit in S
20367 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
20368 \ ******************************\
20369 \ RC5_CommandByteIsDone \ RC5_code --
20370 \ ******************************\
20372 \ ------------------------------\
20373 \ Display IR_RC5 code \
20374 \ ------------------------------\
20375 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
20376 \ ------------------------------\
20377 LO2HI \ switch from assembler to FORTH
20378 ['] LCD_CLEAR IS CR \ redirects CR
20379 ['] LCD_WrC IS EMIT \ redirects EMIT
20380 $10 BASE ! \ change BASE to hexadecimal
20381 CR ." $" 2 U.R \ print IR_RC5 code
20382 ['] (CR) IS CR \ restore CR
20383 ['] (EMIT) IS EMIT \ restore EMIT
20384 HI2LO \ switch from FORTH to assembler
20385 \ ------------------------------\
20386 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
20387 \ ------------------------------\
20388 MOV @PSP+,&BASE \ restore variable BASE
20389 RETI \ CPU is ON, GIE is OFF
20394 \ ------------------------------\
20395 \ TB0CTL = %0000 0010 1001 0100\$3C0
20396 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20397 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20398 \ -- \ID input divider \ 10 = /4
20399 \ -- \MC Mode Control \ 01 = up to TB0CCR0
20400 \ - \TBCLR TimerB Clear
20403 \ --------------------------------\\
20404 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20405 \ -- \CM Capture Mode
20410 \ --- \OUTMOD \ 011 = set/reset
20416 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
20418 \ ------------------------------\
20419 \ set TimerB to make 50kHz PWM \
20420 \ ------------------------------\
20421 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20422 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
20423 \ ------------------------------\
20424 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20425 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
20426 \ ------------------------------\
20427 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20428 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
20429 \ ------------------------------\
20430 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20431 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
20432 \ ------------------------------\
20433 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20434 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
20435 \ ------------------------------\
20436 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
20437 \ ------------------------------\
20438 \ set TimerB to generate PWM for LCD_Vo
20439 \ ------------------------------\
20440 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
20441 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
20442 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20443 \ ------------------------------\
20444 BIS.B #LCDVo,&LCDVo_DIR \
20445 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
20446 \ ------------------------------\
20447 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20448 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20449 \ ------------------------------\
20450 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20451 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20452 \ ------------------------------\
20453 \ WDT interval init part \
20454 \ ------------------------------\
20455 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
20456 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
20457 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
20458 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
20459 \ ------------------------------\
20461 \ ------------------------------\
20462 BIS.B #RC5,&IR_IE \ enable RC5_Int
20463 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20464 \ ------------------------------\
20465 \ init interrupt vectors
20466 \ ------------------------------\
20467 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
20468 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20469 \ ------------------------------\
20470 \ define LPM mode for ACCEPT \
20471 \ ------------------------------\
20472 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20473 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20474 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20476 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
20478 \ ------------------------------\
20480 \ ------------------------------\
20481 $03E8 20_US \ 1- wait 20 ms
20482 $03 TOP_LCD \ 2- send DB5=DB4=1
20483 $CD 20_US \ 3- wait 4,1 ms
20484 $03 TOP_LCD \ 4- send again DB5=DB4=1
20485 $5 20_US \ 5- wait 0,1 ms
20486 $03 TOP_LCD \ 6- send again again DB5=DB4=1
20487 $2 20_US \ wait 40 us = LCD cycle
20488 $02 TOP_LCD \ 7- send DB5=1 DB4=0
20489 $2 20_US \ wait 40 us = LCD cycle
20490 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20491 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20492 LCD_Clear \ 10- "LCD_Clear"
20493 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20494 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20495 LCD_Clear \ 10- "LCD_Clear"
20496 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20497 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20499 ['] (CR) IS CR \ ' (CR) is CR
20500 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
20502 ." RC5toLCD is running. Type STOP to quit"
20503 \ NOECHO \ uncomment to run this app without terminal connexion
20504 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
20505 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
20509 : STOP \ stops multitasking, must to be used before downloading app
20510 ['] (WARM) IS WARM \ remove START app from FORTH init process
20511 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
20519 CODE MAX \ n1 n2 -- n3 signed maximum
20520 CMP @PSP,TOS \ n2-n1
20521 S< ?GOTO FW1 \ n2<n1
20527 CODE MIN \ n1 n2 -- n3 signed minimum
20528 CMP @PSP,TOS \ n2-n1
20529 S< ?GOTO BW1 \ n2<n1
20535 : U.R \ u n -- display u unsigned in n width (n >= 2)
20537 R> OVER - 0 MAX SPACES TYPE
20541 CODE 20_US \ n -- n * 20 us
20542 BEGIN \ 3 cycles loop + 6~
20543 \ MOV #5,W \ 3 MCLK = 1 MHz
20544 \ MOV #23,W \ 3 MCLK = 4 MHz
20545 MOV #51,W \ 3 MCLK = 8 MHz
20546 \ MOV #104,W \ 3 MCLK = 16 MHz
20547 \ MOV #158,W \ 3 MCLK = 24 MHz
20548 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
20558 CODE TOP_LCD \ LCD Sample
20559 \ \ if write : %xxxxWWWW --
20560 \ \ if read : -- %0000RRRR
20561 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20562 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20563 0= IF \ write LCD bits pattern
20564 AND.B #LCD_DB,TOS \
20565 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20566 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20569 THEN \ read LCD bits pattern
20572 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20573 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20574 AND.B #LCD_DB,TOS \
20579 CODE LCD_W \ byte -- write byte to LCD
20581 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20582 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
20583 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20584 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20585 COLON \ high level word starts here
20586 TOP_LCD 2 20_US \ write high nibble first
20591 CODE LCD_WrC \ char -- Write Char
20592 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20597 CODE LCD_WrF \ func -- Write Fonction
20598 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20604 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
20609 $02 LCD_WrF 100 20_us
20613 \ : LCD_Entry_set $04 OR LCD_WrF ;
20615 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
20617 \ : LCD_Display_Shift $10 OR LCD_WrF ;
20619 \ : LCD_Fn_Set $20 OR LCD_WrF ;
20621 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
20623 \ : LCD_Goto $80 OR LCD_WrF ;
20625 \ CODE LCD_R \ -- byte read byte from LCD
20626 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20627 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20628 \ COLON \ starts a FORTH word
20629 \ TOP_LCD 2 20_us \ -- %0000HHHH
20630 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
20631 \ HI2LO \ switch from FORTH to assembler
20632 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
20633 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
20634 \ MOV @RSP+,IP \ restore IP saved by COLON
20639 \ CODE LCD_RdS \ -- status Read Status
20640 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20645 \ CODE LCD_RdC \ -- char Read Char
20646 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20651 \ -------------+------+------+------+------++---+---+---+---+---------+
20652 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
20653 \ -------------+------+------+------+------++---+---+---+---+---------+
20654 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
20655 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
20656 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
20657 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
20658 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
20659 \ -------------+------+------+------+------++---+---+---+---+---------+
20662 \ ******************************\
20663 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20664 \ ******************************\
20665 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
20666 \ ------------------------------\
20667 \ define LPM mode for ACCEPT \
20668 \ ------------------------------\
20669 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20670 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20671 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20672 BIT.B #SW2,&SW2_IN \ test switch S2
20673 0= IF \ case of switch S2 pressed
20674 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
20676 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
20679 BIT.B #SW1,&SW1_IN \ test switch S1 input
20680 0= IF \ case of Switch S1 pressed
20681 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
20683 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
20687 RETI \ CPU is ON, GIE is OFF
20692 \ ------------------------------\
20693 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20694 \ ******************************\
20695 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20696 \ ******************************\
20697 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20698 \ \ SMclock = 8|16|24 MHz
20699 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
20700 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
20701 \ \ SR(9)=new Toggle bit memory (ADD on)
20702 \ ------------------------------\
20703 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
20704 \ ------------------------------\
20705 \ define LPM mode for ACCEPT \
20706 \ ------------------------------\
20707 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20708 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20709 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20710 \ ------------------------------\
20711 \ RC5_FirstStartBitHalfCycle: \
20712 \ ------------------------------\
20713 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
20714 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
20715 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
20716 MOV #1778,X \ RC5_Period in us
20717 MOV #14,W \ count of loop
20719 \ ------------------------------\
20720 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
20721 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
20722 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
20723 \ RC5_Compute_3/4_Period: \ |
20724 RRUM #1,X \ X=1/2 cycle |
20728 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
20729 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
20731 \ ------------------------------\
20732 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
20733 \ ------------------------------\
20734 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20735 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
20736 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20737 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20738 SUB #1,W \ decrement count loop
20739 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
20740 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20741 0<> WHILE \ ----> out of loop ----+
20742 \ RC5_compute_7/4_Time_out: \ |
20743 ADD X,Y \ | out of bound = 7/4 period
20744 \ RC5_WaitHalfCycleP1.2_IFG: \ |
20746 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
20747 0>= IF \ | if cycle time out of bound
20748 BIC #$30,&TA0CTL \ | stop timer_A0
20749 RETI \ | then quit to do nothing
20751 \ ------------------------------\ |
20752 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
20754 MOV &TA0R,X \ | | get new RC5_period value
20755 REPEAT \ ----> loop back --+ |
20756 \ ------------------------------\ |
20757 \ RC5_SampleEndOf: \ <---------------------+
20758 \ ------------------------------\
20759 BIC #$30,&TA0CTL \ stop timer_A0
20760 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
20761 \ ******************************\
20762 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20763 \ ******************************\
20764 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
20765 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
20766 XOR IP,X \ (new XOR old) Toggle bit (13)
20767 BIT #BIT13,X \ X(13) = New_RC5_command
20768 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
20770 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
20771 \ ******************************\
20772 \ RC5_ComputeNewRC5word \
20773 \ ******************************\
20775 MOV &BASE,2(PSP) \ save variable BASE before use
20776 MOV TOS,0(PSP) \ save TOS before use
20777 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
20778 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
20779 \ ******************************\
20780 \ RC5_ComputeC6bit \
20781 \ ******************************\
20782 BIT #$4000,IP \ test /C6 bit in IP
20783 0= IF BIS #$40,TOS \ set C6 bit in S
20784 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
20785 \ ******************************\
20786 \ RC5_CommandByteIsDone \ RC5_code --
20787 \ ******************************\
20789 \ ------------------------------\
20790 \ Display IR_RC5 code \
20791 \ ------------------------------\
20792 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
20793 \ ------------------------------\
20794 LO2HI \ switch from assembler to FORTH
20795 ['] LCD_CLEAR IS CR \ redirects CR
20796 ['] LCD_WrC IS EMIT \ redirects EMIT
20797 $10 BASE ! \ change BASE to hexadecimal
20798 CR ." $" 2 U.R \ print IR_RC5 code
20799 ['] (CR) IS CR \ restore CR
20800 ['] (EMIT) IS EMIT \ restore EMIT
20801 HI2LO \ switch from FORTH to assembler
20802 \ ------------------------------\
20803 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
20804 \ ------------------------------\
20805 MOV @PSP+,&BASE \ restore variable BASE
20806 RETI \ CPU is ON, GIE is OFF
20811 \ ------------------------------\
20812 \ TB0CTL = %0000 0010 1001 0100\$3C0
20813 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20814 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20815 \ -- \ID input divider \ 10 = /4
20816 \ -- \MC Mode Control \ 01 = up to TB0CCR0
20817 \ - \TBCLR TimerB Clear
20820 \ --------------------------------\\
20821 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20822 \ -- \CM Capture Mode
20827 \ --- \OUTMOD \ 011 = set/reset
20833 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
20835 \ ------------------------------\
20836 \ set TimerB to make 50kHz PWM \
20837 \ ------------------------------\
20838 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20839 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
20840 \ ------------------------------\
20841 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
20842 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
20843 \ ------------------------------\
20844 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20845 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
20846 \ ------------------------------\
20847 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20848 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
20849 \ ------------------------------\
20850 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
20851 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
20852 \ ------------------------------\
20853 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
20854 \ ------------------------------\
20855 \ set TimerB to generate PWM for LCD_Vo
20856 \ ------------------------------\
20857 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
20858 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
20859 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20860 \ ------------------------------\
20861 BIS.B #LCDVo,&LCDVo_DIR \
20862 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
20863 \ ------------------------------\
20864 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20865 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20866 \ ------------------------------\
20867 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20868 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20869 \ ------------------------------\
20870 \ WDT interval init part \
20871 \ ------------------------------\
20872 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
20873 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
20874 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
20875 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
20876 \ ------------------------------\
20878 \ ------------------------------\
20879 BIS.B #RC5,&IR_IE \ enable RC5_Int
20880 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20881 \ ------------------------------\
20882 \ init interrupt vectors
20883 \ ------------------------------\
20884 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
20885 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20886 \ ------------------------------\
20887 \ define LPM mode for ACCEPT \
20888 \ ------------------------------\
20889 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20890 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20891 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20893 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
20895 \ ------------------------------\
20897 \ ------------------------------\
20898 $03E8 20_US \ 1- wait 20 ms
20899 $03 TOP_LCD \ 2- send DB5=DB4=1
20900 $CD 20_US \ 3- wait 4,1 ms
20901 $03 TOP_LCD \ 4- send again DB5=DB4=1
20902 $5 20_US \ 5- wait 0,1 ms
20903 $03 TOP_LCD \ 6- send again again DB5=DB4=1
20904 $2 20_US \ wait 40 us = LCD cycle
20905 $02 TOP_LCD \ 7- send DB5=1 DB4=0
20906 $2 20_US \ wait 40 us = LCD cycle
20907 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20908 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20909 LCD_Clear \ 10- "LCD_Clear"
20910 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20911 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20912 LCD_Clear \ 10- "LCD_Clear"
20913 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20914 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20916 ['] (CR) IS CR \ ' (CR) is CR
20917 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
20919 ." RC5toLCD is running. Type STOP to quit"
20920 \ NOECHO \ uncomment to run this app without terminal connexion
20921 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
20922 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
20926 : STOP \ stops multitasking, must to be used before downloading app
20927 ['] (WARM) IS WARM \ remove START app from FORTH init process
20928 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
20936 CODE MAX \ n1 n2 -- n3 signed maximum
20937 CMP @PSP,TOS \ n2-n1
20938 S< ?GOTO FW1 \ n2<n1
20944 CODE MIN \ n1 n2 -- n3 signed minimum
20945 CMP @PSP,TOS \ n2-n1
20946 S< ?GOTO BW1 \ n2<n1
20952 : U.R \ u n -- display u unsigned in n width (n >= 2)
20954 R> OVER - 0 MAX SPACES TYPE
20958 CODE 20_US \ n -- n * 20 us
20959 BEGIN \ 3 cycles loop + 6~
20960 \ MOV #5,W \ 3 MCLK = 1 MHz
20961 \ MOV #23,W \ 3 MCLK = 4 MHz
20962 MOV #51,W \ 3 MCLK = 8 MHz
20963 \ MOV #104,W \ 3 MCLK = 16 MHz
20964 \ MOV #158,W \ 3 MCLK = 24 MHz
20965 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
20975 CODE TOP_LCD \ LCD Sample
20976 \ \ if write : %xxxxWWWW --
20977 \ \ if read : -- %0000RRRR
20978 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20979 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20980 0= IF \ write LCD bits pattern
20981 AND.B #LCD_DB,TOS \
20982 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20983 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20986 THEN \ read LCD bits pattern
20989 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20990 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20991 AND.B #LCD_DB,TOS \
20996 CODE LCD_W \ byte -- write byte to LCD
20998 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
20999 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21000 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21001 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21002 COLON \ high level word starts here
21003 TOP_LCD 2 20_US \ write high nibble first
21008 CODE LCD_WrC \ char -- Write Char
21009 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21014 CODE LCD_WrF \ func -- Write Fonction
21015 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21021 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
21026 $02 LCD_WrF 100 20_us
21030 \ : LCD_Entry_set $04 OR LCD_WrF ;
21032 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
21034 \ : LCD_Display_Shift $10 OR LCD_WrF ;
21036 \ : LCD_Fn_Set $20 OR LCD_WrF ;
21038 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
21040 \ : LCD_Goto $80 OR LCD_WrF ;
21042 \ CODE LCD_R \ -- byte read byte from LCD
21043 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21044 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21045 \ COLON \ starts a FORTH word
21046 \ TOP_LCD 2 20_us \ -- %0000HHHH
21047 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21048 \ HI2LO \ switch from FORTH to assembler
21049 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21050 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21051 \ MOV @RSP+,IP \ restore IP saved by COLON
21056 \ CODE LCD_RdS \ -- status Read Status
21057 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21062 \ CODE LCD_RdC \ -- char Read Char
21063 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21068 \ -------------+------+------+------+------++---+---+---+---+---------+
21069 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
21070 \ -------------+------+------+------+------++---+---+---+---+---------+
21071 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
21072 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
21073 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
21074 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
21075 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
21076 \ -------------+------+------+------+------++---+---+---+---+---------+
21079 \ ******************************\
21080 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21081 \ ******************************\
21082 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
21083 \ ------------------------------\
21084 \ define LPM mode for ACCEPT \
21085 \ ------------------------------\
21086 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21087 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21088 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21089 BIT.B #SW2,&SW2_IN \ test switch S2
21090 0= IF \ case of switch S2 pressed
21091 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
21093 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
21096 BIT.B #SW1,&SW1_IN \ test switch S1 input
21097 0= IF \ case of Switch S1 pressed
21098 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
21100 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
21104 RETI \ CPU is ON, GIE is OFF
21109 \ ------------------------------\
21110 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21111 \ ******************************\
21112 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21113 \ ******************************\
21114 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21115 \ \ SMclock = 8|16|24 MHz
21116 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
21117 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
21118 \ \ SR(9)=new Toggle bit memory (ADD on)
21119 \ ------------------------------\
21120 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
21121 \ ------------------------------\
21122 \ define LPM mode for ACCEPT \
21123 \ ------------------------------\
21124 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21125 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21126 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21127 \ ------------------------------\
21128 \ RC5_FirstStartBitHalfCycle: \
21129 \ ------------------------------\
21130 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
21131 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
21132 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
21133 MOV #1778,X \ RC5_Period in us
21134 MOV #14,W \ count of loop
21136 \ ------------------------------\
21137 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
21138 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
21139 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
21140 \ RC5_Compute_3/4_Period: \ |
21141 RRUM #1,X \ X=1/2 cycle |
21145 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
21146 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
21148 \ ------------------------------\
21149 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
21150 \ ------------------------------\
21151 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21152 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
21153 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21154 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21155 SUB #1,W \ decrement count loop
21156 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
21157 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21158 0<> WHILE \ ----> out of loop ----+
21159 \ RC5_compute_7/4_Time_out: \ |
21160 ADD X,Y \ | out of bound = 7/4 period
21161 \ RC5_WaitHalfCycleP1.2_IFG: \ |
21163 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
21164 0>= IF \ | if cycle time out of bound
21165 BIC #$30,&TA0CTL \ | stop timer_A0
21166 RETI \ | then quit to do nothing
21168 \ ------------------------------\ |
21169 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
21171 MOV &TA0R,X \ | | get new RC5_period value
21172 REPEAT \ ----> loop back --+ |
21173 \ ------------------------------\ |
21174 \ RC5_SampleEndOf: \ <---------------------+
21175 \ ------------------------------\
21176 BIC #$30,&TA0CTL \ stop timer_A0
21177 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
21178 \ ******************************\
21179 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21180 \ ******************************\
21181 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
21182 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
21183 XOR IP,X \ (new XOR old) Toggle bit (13)
21184 BIT #BIT13,X \ X(13) = New_RC5_command
21185 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
21187 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
21188 \ ******************************\
21189 \ RC5_ComputeNewRC5word \
21190 \ ******************************\
21192 MOV &BASE,2(PSP) \ save variable BASE before use
21193 MOV TOS,0(PSP) \ save TOS before use
21194 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
21195 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
21196 \ ******************************\
21197 \ RC5_ComputeC6bit \
21198 \ ******************************\
21199 BIT #$4000,IP \ test /C6 bit in IP
21200 0= IF BIS #$40,TOS \ set C6 bit in S
21201 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
21202 \ ******************************\
21203 \ RC5_CommandByteIsDone \ RC5_code --
21204 \ ******************************\
21206 \ ------------------------------\
21207 \ Display IR_RC5 code \
21208 \ ------------------------------\
21209 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
21210 \ ------------------------------\
21211 LO2HI \ switch from assembler to FORTH
21212 ['] LCD_CLEAR IS CR \ redirects CR
21213 ['] LCD_WrC IS EMIT \ redirects EMIT
21214 $10 BASE ! \ change BASE to hexadecimal
21215 CR ." $" 2 U.R \ print IR_RC5 code
21216 ['] (CR) IS CR \ restore CR
21217 ['] (EMIT) IS EMIT \ restore EMIT
21218 HI2LO \ switch from FORTH to assembler
21219 \ ------------------------------\
21220 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
21221 \ ------------------------------\
21222 MOV @PSP+,&BASE \ restore variable BASE
21223 RETI \ CPU is ON, GIE is OFF
21228 \ ------------------------------\
21229 \ TB0CTL = %0000 0010 1001 0100\$3C0
21230 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21231 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21232 \ -- \ID input divider \ 10 = /4
21233 \ -- \MC Mode Control \ 01 = up to TB0CCR0
21234 \ - \TBCLR TimerB Clear
21237 \ --------------------------------\\
21238 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21239 \ -- \CM Capture Mode
21244 \ --- \OUTMOD \ 011 = set/reset
21250 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
21252 \ ------------------------------\
21253 \ set TimerB to make 50kHz PWM \
21254 \ ------------------------------\
21255 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21256 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
21257 \ ------------------------------\
21258 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21259 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
21260 \ ------------------------------\
21261 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21262 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
21263 \ ------------------------------\
21264 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21265 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
21266 \ ------------------------------\
21267 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21268 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
21269 \ ------------------------------\
21270 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
21271 \ ------------------------------\
21272 \ set TimerB to generate PWM for LCD_Vo
21273 \ ------------------------------\
21274 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
21275 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
21276 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21277 \ ------------------------------\
21278 BIS.B #LCDVo,&LCDVo_DIR \
21279 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
21280 \ ------------------------------\
21281 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21282 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21283 \ ------------------------------\
21284 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21285 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21286 \ ------------------------------\
21287 \ WDT interval init part \
21288 \ ------------------------------\
21289 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
21290 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
21291 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
21292 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
21293 \ ------------------------------\
21295 \ ------------------------------\
21296 BIS.B #RC5,&IR_IE \ enable RC5_Int
21297 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21298 \ ------------------------------\
21299 \ init interrupt vectors
21300 \ ------------------------------\
21301 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
21302 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21303 \ ------------------------------\
21304 \ define LPM mode for ACCEPT \
21305 \ ------------------------------\
21306 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21307 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21308 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21310 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
21312 \ ------------------------------\
21314 \ ------------------------------\
21315 $03E8 20_US \ 1- wait 20 ms
21316 $03 TOP_LCD \ 2- send DB5=DB4=1
21317 $CD 20_US \ 3- wait 4,1 ms
21318 $03 TOP_LCD \ 4- send again DB5=DB4=1
21319 $5 20_US \ 5- wait 0,1 ms
21320 $03 TOP_LCD \ 6- send again again DB5=DB4=1
21321 $2 20_US \ wait 40 us = LCD cycle
21322 $02 TOP_LCD \ 7- send DB5=1 DB4=0
21323 $2 20_US \ wait 40 us = LCD cycle
21324 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21325 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21326 LCD_Clear \ 10- "LCD_Clear"
21327 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21328 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21329 LCD_Clear \ 10- "LCD_Clear"
21330 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21331 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21333 ['] (CR) IS CR \ ' (CR) is CR
21334 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
21336 ." RC5toLCD is running. Type STOP to quit"
21337 \ NOECHO \ uncomment to run this app without terminal connexion
21338 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
21339 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
21343 : STOP \ stops multitasking, must to be used before downloading app
21344 ['] (WARM) IS WARM \ remove START app from FORTH init process
21345 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
21353 CODE MAX \ n1 n2 -- n3 signed maximum
21354 CMP @PSP,TOS \ n2-n1
21355 S< ?GOTO FW1 \ n2<n1
21361 CODE MIN \ n1 n2 -- n3 signed minimum
21362 CMP @PSP,TOS \ n2-n1
21363 S< ?GOTO BW1 \ n2<n1
21369 : U.R \ u n -- display u unsigned in n width (n >= 2)
21371 R> OVER - 0 MAX SPACES TYPE
21375 CODE 20_US \ n -- n * 20 us
21376 BEGIN \ 3 cycles loop + 6~
21377 \ MOV #5,W \ 3 MCLK = 1 MHz
21378 \ MOV #23,W \ 3 MCLK = 4 MHz
21379 MOV #51,W \ 3 MCLK = 8 MHz
21380 \ MOV #104,W \ 3 MCLK = 16 MHz
21381 \ MOV #158,W \ 3 MCLK = 24 MHz
21382 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
21392 CODE TOP_LCD \ LCD Sample
21393 \ \ if write : %xxxxWWWW --
21394 \ \ if read : -- %0000RRRR
21395 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21396 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21397 0= IF \ write LCD bits pattern
21398 AND.B #LCD_DB,TOS \
21399 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21400 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21403 THEN \ read LCD bits pattern
21406 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21407 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21408 AND.B #LCD_DB,TOS \
21413 CODE LCD_W \ byte -- write byte to LCD
21415 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21416 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21417 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21418 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21419 COLON \ high level word starts here
21420 TOP_LCD 2 20_US \ write high nibble first
21425 CODE LCD_WrC \ char -- Write Char
21426 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21431 CODE LCD_WrF \ func -- Write Fonction
21432 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21438 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
21443 $02 LCD_WrF 100 20_us
21447 \ : LCD_Entry_set $04 OR LCD_WrF ;
21449 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
21451 \ : LCD_Display_Shift $10 OR LCD_WrF ;
21453 \ : LCD_Fn_Set $20 OR LCD_WrF ;
21455 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
21457 \ : LCD_Goto $80 OR LCD_WrF ;
21459 \ CODE LCD_R \ -- byte read byte from LCD
21460 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21461 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21462 \ COLON \ starts a FORTH word
21463 \ TOP_LCD 2 20_us \ -- %0000HHHH
21464 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21465 \ HI2LO \ switch from FORTH to assembler
21466 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21467 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21468 \ MOV @RSP+,IP \ restore IP saved by COLON
21473 \ CODE LCD_RdS \ -- status Read Status
21474 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21479 \ CODE LCD_RdC \ -- char Read Char
21480 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21485 \ -------------+------+------+------+------++---+---+---+---+---------+
21486 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
21487 \ -------------+------+------+------+------++---+---+---+---+---------+
21488 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
21489 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
21490 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
21491 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
21492 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
21493 \ -------------+------+------+------+------++---+---+---+---+---------+
21496 \ ******************************\
21497 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21498 \ ******************************\
21499 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
21500 \ ------------------------------\
21501 \ define LPM mode for ACCEPT \
21502 \ ------------------------------\
21503 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21504 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21505 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21506 BIT.B #SW2,&SW2_IN \ test switch S2
21507 0= IF \ case of switch S2 pressed
21508 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
21510 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
21513 BIT.B #SW1,&SW1_IN \ test switch S1 input
21514 0= IF \ case of Switch S1 pressed
21515 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
21517 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
21521 RETI \ CPU is ON, GIE is OFF
21526 \ ------------------------------\
21527 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21528 \ ******************************\
21529 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21530 \ ******************************\
21531 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21532 \ \ SMclock = 8|16|24 MHz
21533 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
21534 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
21535 \ \ SR(9)=new Toggle bit memory (ADD on)
21536 \ ------------------------------\
21537 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
21538 \ ------------------------------\
21539 \ define LPM mode for ACCEPT \
21540 \ ------------------------------\
21541 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21542 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21543 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21544 \ ------------------------------\
21545 \ RC5_FirstStartBitHalfCycle: \
21546 \ ------------------------------\
21547 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
21548 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
21549 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
21550 MOV #1778,X \ RC5_Period in us
21551 MOV #14,W \ count of loop
21553 \ ------------------------------\
21554 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
21555 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
21556 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
21557 \ RC5_Compute_3/4_Period: \ |
21558 RRUM #1,X \ X=1/2 cycle |
21562 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
21563 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
21565 \ ------------------------------\
21566 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
21567 \ ------------------------------\
21568 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21569 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
21570 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21571 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21572 SUB #1,W \ decrement count loop
21573 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
21574 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21575 0<> WHILE \ ----> out of loop ----+
21576 \ RC5_compute_7/4_Time_out: \ |
21577 ADD X,Y \ | out of bound = 7/4 period
21578 \ RC5_WaitHalfCycleP1.2_IFG: \ |
21580 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
21581 0>= IF \ | if cycle time out of bound
21582 BIC #$30,&TA0CTL \ | stop timer_A0
21583 RETI \ | then quit to do nothing
21585 \ ------------------------------\ |
21586 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
21588 MOV &TA0R,X \ | | get new RC5_period value
21589 REPEAT \ ----> loop back --+ |
21590 \ ------------------------------\ |
21591 \ RC5_SampleEndOf: \ <---------------------+
21592 \ ------------------------------\
21593 BIC #$30,&TA0CTL \ stop timer_A0
21594 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
21595 \ ******************************\
21596 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21597 \ ******************************\
21598 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
21599 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
21600 XOR IP,X \ (new XOR old) Toggle bit (13)
21601 BIT #BIT13,X \ X(13) = New_RC5_command
21602 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
21604 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
21605 \ ******************************\
21606 \ RC5_ComputeNewRC5word \
21607 \ ******************************\
21609 MOV &BASE,2(PSP) \ save variable BASE before use
21610 MOV TOS,0(PSP) \ save TOS before use
21611 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
21612 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
21613 \ ******************************\
21614 \ RC5_ComputeC6bit \
21615 \ ******************************\
21616 BIT #$4000,IP \ test /C6 bit in IP
21617 0= IF BIS #$40,TOS \ set C6 bit in S
21618 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
21619 \ ******************************\
21620 \ RC5_CommandByteIsDone \ RC5_code --
21621 \ ******************************\
21623 \ ------------------------------\
21624 \ Display IR_RC5 code \
21625 \ ------------------------------\
21626 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
21627 \ ------------------------------\
21628 LO2HI \ switch from assembler to FORTH
21629 ['] LCD_CLEAR IS CR \ redirects CR
21630 ['] LCD_WrC IS EMIT \ redirects EMIT
21631 $10 BASE ! \ change BASE to hexadecimal
21632 CR ." $" 2 U.R \ print IR_RC5 code
21633 ['] (CR) IS CR \ restore CR
21634 ['] (EMIT) IS EMIT \ restore EMIT
21635 HI2LO \ switch from FORTH to assembler
21636 \ ------------------------------\
21637 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
21638 \ ------------------------------\
21639 MOV @PSP+,&BASE \ restore variable BASE
21640 RETI \ CPU is ON, GIE is OFF
21645 \ ------------------------------\
21646 \ TB0CTL = %0000 0010 1001 0100\$3C0
21647 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21648 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21649 \ -- \ID input divider \ 10 = /4
21650 \ -- \MC Mode Control \ 01 = up to TB0CCR0
21651 \ - \TBCLR TimerB Clear
21654 \ --------------------------------\\
21655 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21656 \ -- \CM Capture Mode
21661 \ --- \OUTMOD \ 011 = set/reset
21667 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
21669 \ ------------------------------\
21670 \ set TimerB to make 50kHz PWM \
21671 \ ------------------------------\
21672 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21673 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
21674 \ ------------------------------\
21675 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
21676 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
21677 \ ------------------------------\
21678 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21679 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
21680 \ ------------------------------\
21681 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21682 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
21683 \ ------------------------------\
21684 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
21685 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
21686 \ ------------------------------\
21687 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
21688 \ ------------------------------\
21689 \ set TimerB to generate PWM for LCD_Vo
21690 \ ------------------------------\
21691 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
21692 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
21693 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21694 \ ------------------------------\
21695 BIS.B #LCDVo,&LCDVo_DIR \
21696 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
21697 \ ------------------------------\
21698 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21699 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21700 \ ------------------------------\
21701 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21702 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21703 \ ------------------------------\
21704 \ WDT interval init part \
21705 \ ------------------------------\
21706 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
21707 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
21708 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
21709 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
21710 \ ------------------------------\
21712 \ ------------------------------\
21713 BIS.B #RC5,&IR_IE \ enable RC5_Int
21714 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21715 \ ------------------------------\
21716 \ init interrupt vectors
21717 \ ------------------------------\
21718 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
21719 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21720 \ ------------------------------\
21721 \ define LPM mode for ACCEPT \
21722 \ ------------------------------\
21723 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21724 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21725 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21727 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
21729 \ ------------------------------\
21731 \ ------------------------------\
21732 $03E8 20_US \ 1- wait 20 ms
21733 $03 TOP_LCD \ 2- send DB5=DB4=1
21734 $CD 20_US \ 3- wait 4,1 ms
21735 $03 TOP_LCD \ 4- send again DB5=DB4=1
21736 $5 20_US \ 5- wait 0,1 ms
21737 $03 TOP_LCD \ 6- send again again DB5=DB4=1
21738 $2 20_US \ wait 40 us = LCD cycle
21739 $02 TOP_LCD \ 7- send DB5=1 DB4=0
21740 $2 20_US \ wait 40 us = LCD cycle
21741 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21742 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21743 LCD_Clear \ 10- "LCD_Clear"
21744 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21745 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21746 LCD_Clear \ 10- "LCD_Clear"
21747 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21748 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21750 ['] (CR) IS CR \ ' (CR) is CR
21751 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
21753 ." RC5toLCD is running. Type STOP to quit"
21754 \ NOECHO \ uncomment to run this app without terminal connexion
21755 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
21756 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
21760 : STOP \ stops multitasking, must to be used before downloading app
21761 ['] (WARM) IS WARM \ remove START app from FORTH init process
21762 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
21770 CODE MAX \ n1 n2 -- n3 signed maximum
21771 CMP @PSP,TOS \ n2-n1
21772 S< ?GOTO FW1 \ n2<n1
21778 CODE MIN \ n1 n2 -- n3 signed minimum
21779 CMP @PSP,TOS \ n2-n1
21780 S< ?GOTO BW1 \ n2<n1
21786 : U.R \ u n -- display u unsigned in n width (n >= 2)
21788 R> OVER - 0 MAX SPACES TYPE
21792 CODE 20_US \ n -- n * 20 us
21793 BEGIN \ 3 cycles loop + 6~
21794 \ MOV #5,W \ 3 MCLK = 1 MHz
21795 \ MOV #23,W \ 3 MCLK = 4 MHz
21796 MOV #51,W \ 3 MCLK = 8 MHz
21797 \ MOV #104,W \ 3 MCLK = 16 MHz
21798 \ MOV #158,W \ 3 MCLK = 24 MHz
21799 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
21809 CODE TOP_LCD \ LCD Sample
21810 \ \ if write : %xxxxWWWW --
21811 \ \ if read : -- %0000RRRR
21812 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21813 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21814 0= IF \ write LCD bits pattern
21815 AND.B #LCD_DB,TOS \
21816 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21817 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21820 THEN \ read LCD bits pattern
21823 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21824 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21825 AND.B #LCD_DB,TOS \
21830 CODE LCD_W \ byte -- write byte to LCD
21832 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
21833 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
21834 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21835 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21836 COLON \ high level word starts here
21837 TOP_LCD 2 20_US \ write high nibble first
21842 CODE LCD_WrC \ char -- Write Char
21843 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21848 CODE LCD_WrF \ func -- Write Fonction
21849 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21855 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
21860 $02 LCD_WrF 100 20_us
21864 \ : LCD_Entry_set $04 OR LCD_WrF ;
21866 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
21868 \ : LCD_Display_Shift $10 OR LCD_WrF ;
21870 \ : LCD_Fn_Set $20 OR LCD_WrF ;
21872 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
21874 \ : LCD_Goto $80 OR LCD_WrF ;
21876 \ CODE LCD_R \ -- byte read byte from LCD
21877 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21878 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21879 \ COLON \ starts a FORTH word
21880 \ TOP_LCD 2 20_us \ -- %0000HHHH
21881 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
21882 \ HI2LO \ switch from FORTH to assembler
21883 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
21884 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
21885 \ MOV @RSP+,IP \ restore IP saved by COLON
21890 \ CODE LCD_RdS \ -- status Read Status
21891 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21896 \ CODE LCD_RdC \ -- char Read Char
21897 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21902 \ -------------+------+------+------+------++---+---+---+---+---------+
21903 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
21904 \ -------------+------+------+------+------++---+---+---+---+---------+
21905 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
21906 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
21907 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
21908 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
21909 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
21910 \ -------------+------+------+------+------++---+---+---+---+---------+
21913 \ ******************************\
21914 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21915 \ ******************************\
21916 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
21917 \ ------------------------------\
21918 \ define LPM mode for ACCEPT \
21919 \ ------------------------------\
21920 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21921 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21922 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21923 BIT.B #SW2,&SW2_IN \ test switch S2
21924 0= IF \ case of switch S2 pressed
21925 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
21927 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
21930 BIT.B #SW1,&SW1_IN \ test switch S1 input
21931 0= IF \ case of Switch S1 pressed
21932 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
21934 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
21938 RETI \ CPU is ON, GIE is OFF
21943 \ ------------------------------\
21944 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21945 \ ******************************\
21946 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21947 \ ******************************\
21948 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21949 \ \ SMclock = 8|16|24 MHz
21950 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
21951 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
21952 \ \ SR(9)=new Toggle bit memory (ADD on)
21953 \ ------------------------------\
21954 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
21955 \ ------------------------------\
21956 \ define LPM mode for ACCEPT \
21957 \ ------------------------------\
21958 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21959 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21960 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21961 \ ------------------------------\
21962 \ RC5_FirstStartBitHalfCycle: \
21963 \ ------------------------------\
21964 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
21965 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
21966 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
21967 MOV #1778,X \ RC5_Period in us
21968 MOV #14,W \ count of loop
21970 \ ------------------------------\
21971 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
21972 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
21973 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
21974 \ RC5_Compute_3/4_Period: \ |
21975 RRUM #1,X \ X=1/2 cycle |
21979 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
21980 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
21982 \ ------------------------------\
21983 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
21984 \ ------------------------------\
21985 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21986 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
21987 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21988 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21989 SUB #1,W \ decrement count loop
21990 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
21991 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21992 0<> WHILE \ ----> out of loop ----+
21993 \ RC5_compute_7/4_Time_out: \ |
21994 ADD X,Y \ | out of bound = 7/4 period
21995 \ RC5_WaitHalfCycleP1.2_IFG: \ |
21997 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
21998 0>= IF \ | if cycle time out of bound
21999 BIC #$30,&TA0CTL \ | stop timer_A0
22000 RETI \ | then quit to do nothing
22002 \ ------------------------------\ |
22003 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
22005 MOV &TA0R,X \ | | get new RC5_period value
22006 REPEAT \ ----> loop back --+ |
22007 \ ------------------------------\ |
22008 \ RC5_SampleEndOf: \ <---------------------+
22009 \ ------------------------------\
22010 BIC #$30,&TA0CTL \ stop timer_A0
22011 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
22012 \ ******************************\
22013 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22014 \ ******************************\
22015 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
22016 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
22017 XOR IP,X \ (new XOR old) Toggle bit (13)
22018 BIT #BIT13,X \ X(13) = New_RC5_command
22019 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
22021 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
22022 \ ******************************\
22023 \ RC5_ComputeNewRC5word \
22024 \ ******************************\
22026 MOV &BASE,2(PSP) \ save variable BASE before use
22027 MOV TOS,0(PSP) \ save TOS before use
22028 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
22029 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
22030 \ ******************************\
22031 \ RC5_ComputeC6bit \
22032 \ ******************************\
22033 BIT #$4000,IP \ test /C6 bit in IP
22034 0= IF BIS #$40,TOS \ set C6 bit in S
22035 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
22036 \ ******************************\
22037 \ RC5_CommandByteIsDone \ RC5_code --
22038 \ ******************************\
22040 \ ------------------------------\
22041 \ Display IR_RC5 code \
22042 \ ------------------------------\
22043 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
22044 \ ------------------------------\
22045 LO2HI \ switch from assembler to FORTH
22046 ['] LCD_CLEAR IS CR \ redirects CR
22047 ['] LCD_WrC IS EMIT \ redirects EMIT
22048 $10 BASE ! \ change BASE to hexadecimal
22049 CR ." $" 2 U.R \ print IR_RC5 code
22050 ['] (CR) IS CR \ restore CR
22051 ['] (EMIT) IS EMIT \ restore EMIT
22052 HI2LO \ switch from FORTH to assembler
22053 \ ------------------------------\
22054 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
22055 \ ------------------------------\
22056 MOV @PSP+,&BASE \ restore variable BASE
22057 RETI \ CPU is ON, GIE is OFF
22062 \ ------------------------------\
22063 \ TB0CTL = %0000 0010 1001 0100\$3C0
22064 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22065 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22066 \ -- \ID input divider \ 10 = /4
22067 \ -- \MC Mode Control \ 01 = up to TB0CCR0
22068 \ - \TBCLR TimerB Clear
22071 \ --------------------------------\\
22072 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22073 \ -- \CM Capture Mode
22078 \ --- \OUTMOD \ 011 = set/reset
22084 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
22086 \ ------------------------------\
22087 \ set TimerB to make 50kHz PWM \
22088 \ ------------------------------\
22089 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22090 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
22091 \ ------------------------------\
22092 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22093 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
22094 \ ------------------------------\
22095 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22096 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
22097 \ ------------------------------\
22098 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22099 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
22100 \ ------------------------------\
22101 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22102 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
22103 \ ------------------------------\
22104 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
22105 \ ------------------------------\
22106 \ set TimerB to generate PWM for LCD_Vo
22107 \ ------------------------------\
22108 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
22109 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
22110 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22111 \ ------------------------------\
22112 BIS.B #LCDVo,&LCDVo_DIR \
22113 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
22114 \ ------------------------------\
22115 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22116 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22117 \ ------------------------------\
22118 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22119 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22120 \ ------------------------------\
22121 \ WDT interval init part \
22122 \ ------------------------------\
22123 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
22124 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
22125 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
22126 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
22127 \ ------------------------------\
22129 \ ------------------------------\
22130 BIS.B #RC5,&IR_IE \ enable RC5_Int
22131 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22132 \ ------------------------------\
22133 \ init interrupt vectors
22134 \ ------------------------------\
22135 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
22136 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22137 \ ------------------------------\
22138 \ define LPM mode for ACCEPT \
22139 \ ------------------------------\
22140 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22141 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22142 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22144 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
22146 \ ------------------------------\
22148 \ ------------------------------\
22149 $03E8 20_US \ 1- wait 20 ms
22150 $03 TOP_LCD \ 2- send DB5=DB4=1
22151 $CD 20_US \ 3- wait 4,1 ms
22152 $03 TOP_LCD \ 4- send again DB5=DB4=1
22153 $5 20_US \ 5- wait 0,1 ms
22154 $03 TOP_LCD \ 6- send again again DB5=DB4=1
22155 $2 20_US \ wait 40 us = LCD cycle
22156 $02 TOP_LCD \ 7- send DB5=1 DB4=0
22157 $2 20_US \ wait 40 us = LCD cycle
22158 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22159 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22160 LCD_Clear \ 10- "LCD_Clear"
22161 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22162 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22163 LCD_Clear \ 10- "LCD_Clear"
22164 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22165 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22167 ['] (CR) IS CR \ ' (CR) is CR
22168 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
22170 ." RC5toLCD is running. Type STOP to quit"
22171 \ NOECHO \ uncomment to run this app without terminal connexion
22172 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
22173 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
22177 : STOP \ stops multitasking, must to be used before downloading app
22178 ['] (WARM) IS WARM \ remove START app from FORTH init process
22179 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
22187 CODE MAX \ n1 n2 -- n3 signed maximum
22188 CMP @PSP,TOS \ n2-n1
22189 S< ?GOTO FW1 \ n2<n1
22195 CODE MIN \ n1 n2 -- n3 signed minimum
22196 CMP @PSP,TOS \ n2-n1
22197 S< ?GOTO BW1 \ n2<n1
22203 : U.R \ u n -- display u unsigned in n width (n >= 2)
22205 R> OVER - 0 MAX SPACES TYPE
22209 CODE 20_US \ n -- n * 20 us
22210 BEGIN \ 3 cycles loop + 6~
22211 \ MOV #5,W \ 3 MCLK = 1 MHz
22212 \ MOV #23,W \ 3 MCLK = 4 MHz
22213 MOV #51,W \ 3 MCLK = 8 MHz
22214 \ MOV #104,W \ 3 MCLK = 16 MHz
22215 \ MOV #158,W \ 3 MCLK = 24 MHz
22216 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
22226 CODE TOP_LCD \ LCD Sample
22227 \ \ if write : %xxxxWWWW --
22228 \ \ if read : -- %0000RRRR
22229 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22230 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22231 0= IF \ write LCD bits pattern
22232 AND.B #LCD_DB,TOS \
22233 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22234 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22237 THEN \ read LCD bits pattern
22240 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22241 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22242 AND.B #LCD_DB,TOS \
22247 CODE LCD_W \ byte -- write byte to LCD
22249 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22250 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22251 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22252 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22253 COLON \ high level word starts here
22254 TOP_LCD 2 20_US \ write high nibble first
22259 CODE LCD_WrC \ char -- Write Char
22260 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22265 CODE LCD_WrF \ func -- Write Fonction
22266 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22272 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
22277 $02 LCD_WrF 100 20_us
22281 \ : LCD_Entry_set $04 OR LCD_WrF ;
22283 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
22285 \ : LCD_Display_Shift $10 OR LCD_WrF ;
22287 \ : LCD_Fn_Set $20 OR LCD_WrF ;
22289 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
22291 \ : LCD_Goto $80 OR LCD_WrF ;
22293 \ CODE LCD_R \ -- byte read byte from LCD
22294 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22295 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22296 \ COLON \ starts a FORTH word
22297 \ TOP_LCD 2 20_us \ -- %0000HHHH
22298 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22299 \ HI2LO \ switch from FORTH to assembler
22300 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22301 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22302 \ MOV @RSP+,IP \ restore IP saved by COLON
22307 \ CODE LCD_RdS \ -- status Read Status
22308 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22313 \ CODE LCD_RdC \ -- char Read Char
22314 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22319 \ -------------+------+------+------+------++---+---+---+---+---------+
22320 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
22321 \ -------------+------+------+------+------++---+---+---+---+---------+
22322 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
22323 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
22324 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
22325 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
22326 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
22327 \ -------------+------+------+------+------++---+---+---+---+---------+
22330 \ ******************************\
22331 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22332 \ ******************************\
22333 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
22334 \ ------------------------------\
22335 \ define LPM mode for ACCEPT \
22336 \ ------------------------------\
22337 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22338 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22339 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22340 BIT.B #SW2,&SW2_IN \ test switch S2
22341 0= IF \ case of switch S2 pressed
22342 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
22344 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
22347 BIT.B #SW1,&SW1_IN \ test switch S1 input
22348 0= IF \ case of Switch S1 pressed
22349 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
22351 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
22355 RETI \ CPU is ON, GIE is OFF
22360 \ ------------------------------\
22361 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22362 \ ******************************\
22363 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22364 \ ******************************\
22365 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22366 \ \ SMclock = 8|16|24 MHz
22367 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
22368 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
22369 \ \ SR(9)=new Toggle bit memory (ADD on)
22370 \ ------------------------------\
22371 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
22372 \ ------------------------------\
22373 \ define LPM mode for ACCEPT \
22374 \ ------------------------------\
22375 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22376 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22377 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22378 \ ------------------------------\
22379 \ RC5_FirstStartBitHalfCycle: \
22380 \ ------------------------------\
22381 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
22382 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
22383 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
22384 MOV #1778,X \ RC5_Period in us
22385 MOV #14,W \ count of loop
22387 \ ------------------------------\
22388 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
22389 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
22390 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
22391 \ RC5_Compute_3/4_Period: \ |
22392 RRUM #1,X \ X=1/2 cycle |
22396 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
22397 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
22399 \ ------------------------------\
22400 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
22401 \ ------------------------------\
22402 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22403 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
22404 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22405 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22406 SUB #1,W \ decrement count loop
22407 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
22408 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22409 0<> WHILE \ ----> out of loop ----+
22410 \ RC5_compute_7/4_Time_out: \ |
22411 ADD X,Y \ | out of bound = 7/4 period
22412 \ RC5_WaitHalfCycleP1.2_IFG: \ |
22414 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
22415 0>= IF \ | if cycle time out of bound
22416 BIC #$30,&TA0CTL \ | stop timer_A0
22417 RETI \ | then quit to do nothing
22419 \ ------------------------------\ |
22420 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
22422 MOV &TA0R,X \ | | get new RC5_period value
22423 REPEAT \ ----> loop back --+ |
22424 \ ------------------------------\ |
22425 \ RC5_SampleEndOf: \ <---------------------+
22426 \ ------------------------------\
22427 BIC #$30,&TA0CTL \ stop timer_A0
22428 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
22429 \ ******************************\
22430 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22431 \ ******************************\
22432 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
22433 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
22434 XOR IP,X \ (new XOR old) Toggle bit (13)
22435 BIT #BIT13,X \ X(13) = New_RC5_command
22436 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
22438 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
22439 \ ******************************\
22440 \ RC5_ComputeNewRC5word \
22441 \ ******************************\
22443 MOV &BASE,2(PSP) \ save variable BASE before use
22444 MOV TOS,0(PSP) \ save TOS before use
22445 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
22446 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
22447 \ ******************************\
22448 \ RC5_ComputeC6bit \
22449 \ ******************************\
22450 BIT #$4000,IP \ test /C6 bit in IP
22451 0= IF BIS #$40,TOS \ set C6 bit in S
22452 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
22453 \ ******************************\
22454 \ RC5_CommandByteIsDone \ RC5_code --
22455 \ ******************************\
22457 \ ------------------------------\
22458 \ Display IR_RC5 code \
22459 \ ------------------------------\
22460 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
22461 \ ------------------------------\
22462 LO2HI \ switch from assembler to FORTH
22463 ['] LCD_CLEAR IS CR \ redirects CR
22464 ['] LCD_WrC IS EMIT \ redirects EMIT
22465 $10 BASE ! \ change BASE to hexadecimal
22466 CR ." $" 2 U.R \ print IR_RC5 code
22467 ['] (CR) IS CR \ restore CR
22468 ['] (EMIT) IS EMIT \ restore EMIT
22469 HI2LO \ switch from FORTH to assembler
22470 \ ------------------------------\
22471 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
22472 \ ------------------------------\
22473 MOV @PSP+,&BASE \ restore variable BASE
22474 RETI \ CPU is ON, GIE is OFF
22479 \ ------------------------------\
22480 \ TB0CTL = %0000 0010 1001 0100\$3C0
22481 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22482 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22483 \ -- \ID input divider \ 10 = /4
22484 \ -- \MC Mode Control \ 01 = up to TB0CCR0
22485 \ - \TBCLR TimerB Clear
22488 \ --------------------------------\\
22489 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22490 \ -- \CM Capture Mode
22495 \ --- \OUTMOD \ 011 = set/reset
22501 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
22503 \ ------------------------------\
22504 \ set TimerB to make 50kHz PWM \
22505 \ ------------------------------\
22506 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22507 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
22508 \ ------------------------------\
22509 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22510 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
22511 \ ------------------------------\
22512 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22513 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
22514 \ ------------------------------\
22515 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22516 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
22517 \ ------------------------------\
22518 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22519 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
22520 \ ------------------------------\
22521 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
22522 \ ------------------------------\
22523 \ set TimerB to generate PWM for LCD_Vo
22524 \ ------------------------------\
22525 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
22526 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
22527 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22528 \ ------------------------------\
22529 BIS.B #LCDVo,&LCDVo_DIR \
22530 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
22531 \ ------------------------------\
22532 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22533 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22534 \ ------------------------------\
22535 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22536 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22537 \ ------------------------------\
22538 \ WDT interval init part \
22539 \ ------------------------------\
22540 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
22541 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
22542 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
22543 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
22544 \ ------------------------------\
22546 \ ------------------------------\
22547 BIS.B #RC5,&IR_IE \ enable RC5_Int
22548 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22549 \ ------------------------------\
22550 \ init interrupt vectors
22551 \ ------------------------------\
22552 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
22553 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22554 \ ------------------------------\
22555 \ define LPM mode for ACCEPT \
22556 \ ------------------------------\
22557 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22558 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22559 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22561 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
22563 \ ------------------------------\
22565 \ ------------------------------\
22566 $03E8 20_US \ 1- wait 20 ms
22567 $03 TOP_LCD \ 2- send DB5=DB4=1
22568 $CD 20_US \ 3- wait 4,1 ms
22569 $03 TOP_LCD \ 4- send again DB5=DB4=1
22570 $5 20_US \ 5- wait 0,1 ms
22571 $03 TOP_LCD \ 6- send again again DB5=DB4=1
22572 $2 20_US \ wait 40 us = LCD cycle
22573 $02 TOP_LCD \ 7- send DB5=1 DB4=0
22574 $2 20_US \ wait 40 us = LCD cycle
22575 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22576 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22577 LCD_Clear \ 10- "LCD_Clear"
22578 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22579 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22580 LCD_Clear \ 10- "LCD_Clear"
22581 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22582 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22584 ['] (CR) IS CR \ ' (CR) is CR
22585 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
22587 ." RC5toLCD is running. Type STOP to quit"
22588 \ NOECHO \ uncomment to run this app without terminal connexion
22589 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
22590 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
22594 : STOP \ stops multitasking, must to be used before downloading app
22595 ['] (WARM) IS WARM \ remove START app from FORTH init process
22596 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
22604 CODE MAX \ n1 n2 -- n3 signed maximum
22605 CMP @PSP,TOS \ n2-n1
22606 S< ?GOTO FW1 \ n2<n1
22612 CODE MIN \ n1 n2 -- n3 signed minimum
22613 CMP @PSP,TOS \ n2-n1
22614 S< ?GOTO BW1 \ n2<n1
22620 : U.R \ u n -- display u unsigned in n width (n >= 2)
22622 R> OVER - 0 MAX SPACES TYPE
22626 CODE 20_US \ n -- n * 20 us
22627 BEGIN \ 3 cycles loop + 6~
22628 \ MOV #5,W \ 3 MCLK = 1 MHz
22629 \ MOV #23,W \ 3 MCLK = 4 MHz
22630 MOV #51,W \ 3 MCLK = 8 MHz
22631 \ MOV #104,W \ 3 MCLK = 16 MHz
22632 \ MOV #158,W \ 3 MCLK = 24 MHz
22633 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
22643 CODE TOP_LCD \ LCD Sample
22644 \ \ if write : %xxxxWWWW --
22645 \ \ if read : -- %0000RRRR
22646 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22647 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22648 0= IF \ write LCD bits pattern
22649 AND.B #LCD_DB,TOS \
22650 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22651 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22654 THEN \ read LCD bits pattern
22657 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22658 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22659 AND.B #LCD_DB,TOS \
22664 CODE LCD_W \ byte -- write byte to LCD
22666 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
22667 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
22668 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22669 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22670 COLON \ high level word starts here
22671 TOP_LCD 2 20_US \ write high nibble first
22676 CODE LCD_WrC \ char -- Write Char
22677 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22682 CODE LCD_WrF \ func -- Write Fonction
22683 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22689 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
22694 $02 LCD_WrF 100 20_us
22698 \ : LCD_Entry_set $04 OR LCD_WrF ;
22700 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
22702 \ : LCD_Display_Shift $10 OR LCD_WrF ;
22704 \ : LCD_Fn_Set $20 OR LCD_WrF ;
22706 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
22708 \ : LCD_Goto $80 OR LCD_WrF ;
22710 \ CODE LCD_R \ -- byte read byte from LCD
22711 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22712 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22713 \ COLON \ starts a FORTH word
22714 \ TOP_LCD 2 20_us \ -- %0000HHHH
22715 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
22716 \ HI2LO \ switch from FORTH to assembler
22717 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
22718 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
22719 \ MOV @RSP+,IP \ restore IP saved by COLON
22724 \ CODE LCD_RdS \ -- status Read Status
22725 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22730 \ CODE LCD_RdC \ -- char Read Char
22731 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22736 \ -------------+------+------+------+------++---+---+---+---+---------+
22737 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
22738 \ -------------+------+------+------+------++---+---+---+---+---------+
22739 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
22740 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
22741 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
22742 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
22743 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
22744 \ -------------+------+------+------+------++---+---+---+---+---------+
22747 \ ******************************\
22748 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22749 \ ******************************\
22750 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
22751 \ ------------------------------\
22752 \ define LPM mode for ACCEPT \
22753 \ ------------------------------\
22754 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22755 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22756 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22757 BIT.B #SW2,&SW2_IN \ test switch S2
22758 0= IF \ case of switch S2 pressed
22759 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
22761 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
22764 BIT.B #SW1,&SW1_IN \ test switch S1 input
22765 0= IF \ case of Switch S1 pressed
22766 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
22768 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
22772 RETI \ CPU is ON, GIE is OFF
22777 \ ------------------------------\
22778 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22779 \ ******************************\
22780 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22781 \ ******************************\
22782 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22783 \ \ SMclock = 8|16|24 MHz
22784 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
22785 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
22786 \ \ SR(9)=new Toggle bit memory (ADD on)
22787 \ ------------------------------\
22788 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
22789 \ ------------------------------\
22790 \ define LPM mode for ACCEPT \
22791 \ ------------------------------\
22792 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22793 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22794 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22795 \ ------------------------------\
22796 \ RC5_FirstStartBitHalfCycle: \
22797 \ ------------------------------\
22798 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
22799 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
22800 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
22801 MOV #1778,X \ RC5_Period in us
22802 MOV #14,W \ count of loop
22804 \ ------------------------------\
22805 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
22806 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
22807 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
22808 \ RC5_Compute_3/4_Period: \ |
22809 RRUM #1,X \ X=1/2 cycle |
22813 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
22814 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
22816 \ ------------------------------\
22817 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
22818 \ ------------------------------\
22819 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22820 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
22821 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22822 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22823 SUB #1,W \ decrement count loop
22824 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
22825 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22826 0<> WHILE \ ----> out of loop ----+
22827 \ RC5_compute_7/4_Time_out: \ |
22828 ADD X,Y \ | out of bound = 7/4 period
22829 \ RC5_WaitHalfCycleP1.2_IFG: \ |
22831 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
22832 0>= IF \ | if cycle time out of bound
22833 BIC #$30,&TA0CTL \ | stop timer_A0
22834 RETI \ | then quit to do nothing
22836 \ ------------------------------\ |
22837 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
22839 MOV &TA0R,X \ | | get new RC5_period value
22840 REPEAT \ ----> loop back --+ |
22841 \ ------------------------------\ |
22842 \ RC5_SampleEndOf: \ <---------------------+
22843 \ ------------------------------\
22844 BIC #$30,&TA0CTL \ stop timer_A0
22845 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
22846 \ ******************************\
22847 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22848 \ ******************************\
22849 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
22850 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
22851 XOR IP,X \ (new XOR old) Toggle bit (13)
22852 BIT #BIT13,X \ X(13) = New_RC5_command
22853 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
22855 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
22856 \ ******************************\
22857 \ RC5_ComputeNewRC5word \
22858 \ ******************************\
22860 MOV &BASE,2(PSP) \ save variable BASE before use
22861 MOV TOS,0(PSP) \ save TOS before use
22862 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
22863 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
22864 \ ******************************\
22865 \ RC5_ComputeC6bit \
22866 \ ******************************\
22867 BIT #$4000,IP \ test /C6 bit in IP
22868 0= IF BIS #$40,TOS \ set C6 bit in S
22869 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
22870 \ ******************************\
22871 \ RC5_CommandByteIsDone \ RC5_code --
22872 \ ******************************\
22874 \ ------------------------------\
22875 \ Display IR_RC5 code \
22876 \ ------------------------------\
22877 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
22878 \ ------------------------------\
22879 LO2HI \ switch from assembler to FORTH
22880 ['] LCD_CLEAR IS CR \ redirects CR
22881 ['] LCD_WrC IS EMIT \ redirects EMIT
22882 $10 BASE ! \ change BASE to hexadecimal
22883 CR ." $" 2 U.R \ print IR_RC5 code
22884 ['] (CR) IS CR \ restore CR
22885 ['] (EMIT) IS EMIT \ restore EMIT
22886 HI2LO \ switch from FORTH to assembler
22887 \ ------------------------------\
22888 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
22889 \ ------------------------------\
22890 MOV @PSP+,&BASE \ restore variable BASE
22891 RETI \ CPU is ON, GIE is OFF
22896 \ ------------------------------\
22897 \ TB0CTL = %0000 0010 1001 0100\$3C0
22898 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22899 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22900 \ -- \ID input divider \ 10 = /4
22901 \ -- \MC Mode Control \ 01 = up to TB0CCR0
22902 \ - \TBCLR TimerB Clear
22905 \ --------------------------------\\
22906 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22907 \ -- \CM Capture Mode
22912 \ --- \OUTMOD \ 011 = set/reset
22918 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
22920 \ ------------------------------\
22921 \ set TimerB to make 50kHz PWM \
22922 \ ------------------------------\
22923 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22924 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
22925 \ ------------------------------\
22926 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
22927 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
22928 \ ------------------------------\
22929 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22930 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
22931 \ ------------------------------\
22932 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22933 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
22934 \ ------------------------------\
22935 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
22936 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
22937 \ ------------------------------\
22938 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
22939 \ ------------------------------\
22940 \ set TimerB to generate PWM for LCD_Vo
22941 \ ------------------------------\
22942 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
22943 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
22944 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22945 \ ------------------------------\
22946 BIS.B #LCDVo,&LCDVo_DIR \
22947 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
22948 \ ------------------------------\
22949 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22950 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22951 \ ------------------------------\
22952 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22953 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22954 \ ------------------------------\
22955 \ WDT interval init part \
22956 \ ------------------------------\
22957 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
22958 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
22959 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
22960 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
22961 \ ------------------------------\
22963 \ ------------------------------\
22964 BIS.B #RC5,&IR_IE \ enable RC5_Int
22965 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22966 \ ------------------------------\
22967 \ init interrupt vectors
22968 \ ------------------------------\
22969 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
22970 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22971 \ ------------------------------\
22972 \ define LPM mode for ACCEPT \
22973 \ ------------------------------\
22974 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22975 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22976 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22978 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
22980 \ ------------------------------\
22982 \ ------------------------------\
22983 $03E8 20_US \ 1- wait 20 ms
22984 $03 TOP_LCD \ 2- send DB5=DB4=1
22985 $CD 20_US \ 3- wait 4,1 ms
22986 $03 TOP_LCD \ 4- send again DB5=DB4=1
22987 $5 20_US \ 5- wait 0,1 ms
22988 $03 TOP_LCD \ 6- send again again DB5=DB4=1
22989 $2 20_US \ wait 40 us = LCD cycle
22990 $02 TOP_LCD \ 7- send DB5=1 DB4=0
22991 $2 20_US \ wait 40 us = LCD cycle
22992 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22993 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22994 LCD_Clear \ 10- "LCD_Clear"
22995 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22996 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22997 LCD_Clear \ 10- "LCD_Clear"
22998 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22999 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23001 ['] (CR) IS CR \ ' (CR) is CR
23002 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
23004 ." RC5toLCD is running. Type STOP to quit"
23005 \ NOECHO \ uncomment to run this app without terminal connexion
23006 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
23007 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
23011 : STOP \ stops multitasking, must to be used before downloading app
23012 ['] (WARM) IS WARM \ remove START app from FORTH init process
23013 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
23021 CODE MAX \ n1 n2 -- n3 signed maximum
23022 CMP @PSP,TOS \ n2-n1
23023 S< ?GOTO FW1 \ n2<n1
23029 CODE MIN \ n1 n2 -- n3 signed minimum
23030 CMP @PSP,TOS \ n2-n1
23031 S< ?GOTO BW1 \ n2<n1
23037 : U.R \ u n -- display u unsigned in n width (n >= 2)
23039 R> OVER - 0 MAX SPACES TYPE
23043 CODE 20_US \ n -- n * 20 us
23044 BEGIN \ 3 cycles loop + 6~
23045 \ MOV #5,W \ 3 MCLK = 1 MHz
23046 \ MOV #23,W \ 3 MCLK = 4 MHz
23047 MOV #51,W \ 3 MCLK = 8 MHz
23048 \ MOV #104,W \ 3 MCLK = 16 MHz
23049 \ MOV #158,W \ 3 MCLK = 24 MHz
23050 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
23060 CODE TOP_LCD \ LCD Sample
23061 \ \ if write : %xxxxWWWW --
23062 \ \ if read : -- %0000RRRR
23063 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23064 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23065 0= IF \ write LCD bits pattern
23066 AND.B #LCD_DB,TOS \
23067 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23068 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23071 THEN \ read LCD bits pattern
23074 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23075 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23076 AND.B #LCD_DB,TOS \
23081 CODE LCD_W \ byte -- write byte to LCD
23083 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23084 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23085 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23086 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23087 COLON \ high level word starts here
23088 TOP_LCD 2 20_US \ write high nibble first
23093 CODE LCD_WrC \ char -- Write Char
23094 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23099 CODE LCD_WrF \ func -- Write Fonction
23100 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23106 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
23111 $02 LCD_WrF 100 20_us
23115 \ : LCD_Entry_set $04 OR LCD_WrF ;
23117 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
23119 \ : LCD_Display_Shift $10 OR LCD_WrF ;
23121 \ : LCD_Fn_Set $20 OR LCD_WrF ;
23123 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
23125 \ : LCD_Goto $80 OR LCD_WrF ;
23127 \ CODE LCD_R \ -- byte read byte from LCD
23128 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23129 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23130 \ COLON \ starts a FORTH word
23131 \ TOP_LCD 2 20_us \ -- %0000HHHH
23132 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23133 \ HI2LO \ switch from FORTH to assembler
23134 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23135 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23136 \ MOV @RSP+,IP \ restore IP saved by COLON
23141 \ CODE LCD_RdS \ -- status Read Status
23142 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23147 \ CODE LCD_RdC \ -- char Read Char
23148 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23153 \ -------------+------+------+------+------++---+---+---+---+---------+
23154 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
23155 \ -------------+------+------+------+------++---+---+---+---+---------+
23156 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
23157 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
23158 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
23159 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
23160 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
23161 \ -------------+------+------+------+------++---+---+---+---+---------+
23164 \ ******************************\
23165 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23166 \ ******************************\
23167 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
23168 \ ------------------------------\
23169 \ define LPM mode for ACCEPT \
23170 \ ------------------------------\
23171 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23172 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23173 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23174 BIT.B #SW2,&SW2_IN \ test switch S2
23175 0= IF \ case of switch S2 pressed
23176 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
23178 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
23181 BIT.B #SW1,&SW1_IN \ test switch S1 input
23182 0= IF \ case of Switch S1 pressed
23183 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
23185 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
23189 RETI \ CPU is ON, GIE is OFF
23194 \ ------------------------------\
23195 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23196 \ ******************************\
23197 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23198 \ ******************************\
23199 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23200 \ \ SMclock = 8|16|24 MHz
23201 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
23202 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
23203 \ \ SR(9)=new Toggle bit memory (ADD on)
23204 \ ------------------------------\
23205 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
23206 \ ------------------------------\
23207 \ define LPM mode for ACCEPT \
23208 \ ------------------------------\
23209 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23210 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23211 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23212 \ ------------------------------\
23213 \ RC5_FirstStartBitHalfCycle: \
23214 \ ------------------------------\
23215 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
23216 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
23217 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
23218 MOV #1778,X \ RC5_Period in us
23219 MOV #14,W \ count of loop
23221 \ ------------------------------\
23222 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
23223 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
23224 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
23225 \ RC5_Compute_3/4_Period: \ |
23226 RRUM #1,X \ X=1/2 cycle |
23230 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
23231 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
23233 \ ------------------------------\
23234 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
23235 \ ------------------------------\
23236 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23237 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
23238 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23239 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23240 SUB #1,W \ decrement count loop
23241 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
23242 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23243 0<> WHILE \ ----> out of loop ----+
23244 \ RC5_compute_7/4_Time_out: \ |
23245 ADD X,Y \ | out of bound = 7/4 period
23246 \ RC5_WaitHalfCycleP1.2_IFG: \ |
23248 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
23249 0>= IF \ | if cycle time out of bound
23250 BIC #$30,&TA0CTL \ | stop timer_A0
23251 RETI \ | then quit to do nothing
23253 \ ------------------------------\ |
23254 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
23256 MOV &TA0R,X \ | | get new RC5_period value
23257 REPEAT \ ----> loop back --+ |
23258 \ ------------------------------\ |
23259 \ RC5_SampleEndOf: \ <---------------------+
23260 \ ------------------------------\
23261 BIC #$30,&TA0CTL \ stop timer_A0
23262 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
23263 \ ******************************\
23264 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23265 \ ******************************\
23266 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
23267 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
23268 XOR IP,X \ (new XOR old) Toggle bit (13)
23269 BIT #BIT13,X \ X(13) = New_RC5_command
23270 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
23272 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
23273 \ ******************************\
23274 \ RC5_ComputeNewRC5word \
23275 \ ******************************\
23277 MOV &BASE,2(PSP) \ save variable BASE before use
23278 MOV TOS,0(PSP) \ save TOS before use
23279 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
23280 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
23281 \ ******************************\
23282 \ RC5_ComputeC6bit \
23283 \ ******************************\
23284 BIT #$4000,IP \ test /C6 bit in IP
23285 0= IF BIS #$40,TOS \ set C6 bit in S
23286 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
23287 \ ******************************\
23288 \ RC5_CommandByteIsDone \ RC5_code --
23289 \ ******************************\
23291 \ ------------------------------\
23292 \ Display IR_RC5 code \
23293 \ ------------------------------\
23294 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
23295 \ ------------------------------\
23296 LO2HI \ switch from assembler to FORTH
23297 ['] LCD_CLEAR IS CR \ redirects CR
23298 ['] LCD_WrC IS EMIT \ redirects EMIT
23299 $10 BASE ! \ change BASE to hexadecimal
23300 CR ." $" 2 U.R \ print IR_RC5 code
23301 ['] (CR) IS CR \ restore CR
23302 ['] (EMIT) IS EMIT \ restore EMIT
23303 HI2LO \ switch from FORTH to assembler
23304 \ ------------------------------\
23305 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
23306 \ ------------------------------\
23307 MOV @PSP+,&BASE \ restore variable BASE
23308 RETI \ CPU is ON, GIE is OFF
23313 \ ------------------------------\
23314 \ TB0CTL = %0000 0010 1001 0100\$3C0
23315 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23316 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23317 \ -- \ID input divider \ 10 = /4
23318 \ -- \MC Mode Control \ 01 = up to TB0CCR0
23319 \ - \TBCLR TimerB Clear
23322 \ --------------------------------\\
23323 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23324 \ -- \CM Capture Mode
23329 \ --- \OUTMOD \ 011 = set/reset
23335 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
23337 \ ------------------------------\
23338 \ set TimerB to make 50kHz PWM \
23339 \ ------------------------------\
23340 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23341 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
23342 \ ------------------------------\
23343 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23344 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
23345 \ ------------------------------\
23346 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23347 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
23348 \ ------------------------------\
23349 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23350 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
23351 \ ------------------------------\
23352 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23353 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
23354 \ ------------------------------\
23355 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
23356 \ ------------------------------\
23357 \ set TimerB to generate PWM for LCD_Vo
23358 \ ------------------------------\
23359 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
23360 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
23361 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23362 \ ------------------------------\
23363 BIS.B #LCDVo,&LCDVo_DIR \
23364 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
23365 \ ------------------------------\
23366 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23367 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23368 \ ------------------------------\
23369 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23370 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23371 \ ------------------------------\
23372 \ WDT interval init part \
23373 \ ------------------------------\
23374 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
23375 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
23376 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
23377 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
23378 \ ------------------------------\
23380 \ ------------------------------\
23381 BIS.B #RC5,&IR_IE \ enable RC5_Int
23382 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23383 \ ------------------------------\
23384 \ init interrupt vectors
23385 \ ------------------------------\
23386 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
23387 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23388 \ ------------------------------\
23389 \ define LPM mode for ACCEPT \
23390 \ ------------------------------\
23391 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23392 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23393 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23395 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
23397 \ ------------------------------\
23399 \ ------------------------------\
23400 $03E8 20_US \ 1- wait 20 ms
23401 $03 TOP_LCD \ 2- send DB5=DB4=1
23402 $CD 20_US \ 3- wait 4,1 ms
23403 $03 TOP_LCD \ 4- send again DB5=DB4=1
23404 $5 20_US \ 5- wait 0,1 ms
23405 $03 TOP_LCD \ 6- send again again DB5=DB4=1
23406 $2 20_US \ wait 40 us = LCD cycle
23407 $02 TOP_LCD \ 7- send DB5=1 DB4=0
23408 $2 20_US \ wait 40 us = LCD cycle
23409 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23410 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23411 LCD_Clear \ 10- "LCD_Clear"
23412 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23413 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23414 LCD_Clear \ 10- "LCD_Clear"
23415 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23416 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23418 ['] (CR) IS CR \ ' (CR) is CR
23419 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
23421 ." RC5toLCD is running. Type STOP to quit"
23422 \ NOECHO \ uncomment to run this app without terminal connexion
23423 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
23424 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
23428 : STOP \ stops multitasking, must to be used before downloading app
23429 ['] (WARM) IS WARM \ remove START app from FORTH init process
23430 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
23438 CODE MAX \ n1 n2 -- n3 signed maximum
23439 CMP @PSP,TOS \ n2-n1
23440 S< ?GOTO FW1 \ n2<n1
23446 CODE MIN \ n1 n2 -- n3 signed minimum
23447 CMP @PSP,TOS \ n2-n1
23448 S< ?GOTO BW1 \ n2<n1
23454 : U.R \ u n -- display u unsigned in n width (n >= 2)
23456 R> OVER - 0 MAX SPACES TYPE
23460 CODE 20_US \ n -- n * 20 us
23461 BEGIN \ 3 cycles loop + 6~
23462 \ MOV #5,W \ 3 MCLK = 1 MHz
23463 \ MOV #23,W \ 3 MCLK = 4 MHz
23464 MOV #51,W \ 3 MCLK = 8 MHz
23465 \ MOV #104,W \ 3 MCLK = 16 MHz
23466 \ MOV #158,W \ 3 MCLK = 24 MHz
23467 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
23477 CODE TOP_LCD \ LCD Sample
23478 \ \ if write : %xxxxWWWW --
23479 \ \ if read : -- %0000RRRR
23480 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23481 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23482 0= IF \ write LCD bits pattern
23483 AND.B #LCD_DB,TOS \
23484 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23485 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23488 THEN \ read LCD bits pattern
23491 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23492 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23493 AND.B #LCD_DB,TOS \
23498 CODE LCD_W \ byte -- write byte to LCD
23500 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23501 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23502 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23503 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23504 COLON \ high level word starts here
23505 TOP_LCD 2 20_US \ write high nibble first
23510 CODE LCD_WrC \ char -- Write Char
23511 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23516 CODE LCD_WrF \ func -- Write Fonction
23517 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23523 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
23528 $02 LCD_WrF 100 20_us
23532 \ : LCD_Entry_set $04 OR LCD_WrF ;
23534 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
23536 \ : LCD_Display_Shift $10 OR LCD_WrF ;
23538 \ : LCD_Fn_Set $20 OR LCD_WrF ;
23540 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
23542 \ : LCD_Goto $80 OR LCD_WrF ;
23544 \ CODE LCD_R \ -- byte read byte from LCD
23545 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23546 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23547 \ COLON \ starts a FORTH word
23548 \ TOP_LCD 2 20_us \ -- %0000HHHH
23549 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23550 \ HI2LO \ switch from FORTH to assembler
23551 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23552 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23553 \ MOV @RSP+,IP \ restore IP saved by COLON
23558 \ CODE LCD_RdS \ -- status Read Status
23559 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23564 \ CODE LCD_RdC \ -- char Read Char
23565 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23570 \ -------------+------+------+------+------++---+---+---+---+---------+
23571 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
23572 \ -------------+------+------+------+------++---+---+---+---+---------+
23573 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
23574 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
23575 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
23576 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
23577 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
23578 \ -------------+------+------+------+------++---+---+---+---+---------+
23581 \ ******************************\
23582 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23583 \ ******************************\
23584 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
23585 \ ------------------------------\
23586 \ define LPM mode for ACCEPT \
23587 \ ------------------------------\
23588 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23589 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23590 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23591 BIT.B #SW2,&SW2_IN \ test switch S2
23592 0= IF \ case of switch S2 pressed
23593 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
23595 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
23598 BIT.B #SW1,&SW1_IN \ test switch S1 input
23599 0= IF \ case of Switch S1 pressed
23600 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
23602 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
23606 RETI \ CPU is ON, GIE is OFF
23611 \ ------------------------------\
23612 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23613 \ ******************************\
23614 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23615 \ ******************************\
23616 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23617 \ \ SMclock = 8|16|24 MHz
23618 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
23619 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
23620 \ \ SR(9)=new Toggle bit memory (ADD on)
23621 \ ------------------------------\
23622 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
23623 \ ------------------------------\
23624 \ define LPM mode for ACCEPT \
23625 \ ------------------------------\
23626 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23627 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23628 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23629 \ ------------------------------\
23630 \ RC5_FirstStartBitHalfCycle: \
23631 \ ------------------------------\
23632 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
23633 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
23634 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
23635 MOV #1778,X \ RC5_Period in us
23636 MOV #14,W \ count of loop
23638 \ ------------------------------\
23639 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
23640 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
23641 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
23642 \ RC5_Compute_3/4_Period: \ |
23643 RRUM #1,X \ X=1/2 cycle |
23647 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
23648 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
23650 \ ------------------------------\
23651 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
23652 \ ------------------------------\
23653 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23654 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
23655 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23656 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23657 SUB #1,W \ decrement count loop
23658 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
23659 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23660 0<> WHILE \ ----> out of loop ----+
23661 \ RC5_compute_7/4_Time_out: \ |
23662 ADD X,Y \ | out of bound = 7/4 period
23663 \ RC5_WaitHalfCycleP1.2_IFG: \ |
23665 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
23666 0>= IF \ | if cycle time out of bound
23667 BIC #$30,&TA0CTL \ | stop timer_A0
23668 RETI \ | then quit to do nothing
23670 \ ------------------------------\ |
23671 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
23673 MOV &TA0R,X \ | | get new RC5_period value
23674 REPEAT \ ----> loop back --+ |
23675 \ ------------------------------\ |
23676 \ RC5_SampleEndOf: \ <---------------------+
23677 \ ------------------------------\
23678 BIC #$30,&TA0CTL \ stop timer_A0
23679 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
23680 \ ******************************\
23681 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23682 \ ******************************\
23683 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
23684 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
23685 XOR IP,X \ (new XOR old) Toggle bit (13)
23686 BIT #BIT13,X \ X(13) = New_RC5_command
23687 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
23689 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
23690 \ ******************************\
23691 \ RC5_ComputeNewRC5word \
23692 \ ******************************\
23694 MOV &BASE,2(PSP) \ save variable BASE before use
23695 MOV TOS,0(PSP) \ save TOS before use
23696 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
23697 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
23698 \ ******************************\
23699 \ RC5_ComputeC6bit \
23700 \ ******************************\
23701 BIT #$4000,IP \ test /C6 bit in IP
23702 0= IF BIS #$40,TOS \ set C6 bit in S
23703 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
23704 \ ******************************\
23705 \ RC5_CommandByteIsDone \ RC5_code --
23706 \ ******************************\
23708 \ ------------------------------\
23709 \ Display IR_RC5 code \
23710 \ ------------------------------\
23711 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
23712 \ ------------------------------\
23713 LO2HI \ switch from assembler to FORTH
23714 ['] LCD_CLEAR IS CR \ redirects CR
23715 ['] LCD_WrC IS EMIT \ redirects EMIT
23716 $10 BASE ! \ change BASE to hexadecimal
23717 CR ." $" 2 U.R \ print IR_RC5 code
23718 ['] (CR) IS CR \ restore CR
23719 ['] (EMIT) IS EMIT \ restore EMIT
23720 HI2LO \ switch from FORTH to assembler
23721 \ ------------------------------\
23722 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
23723 \ ------------------------------\
23724 MOV @PSP+,&BASE \ restore variable BASE
23725 RETI \ CPU is ON, GIE is OFF
23730 \ ------------------------------\
23731 \ TB0CTL = %0000 0010 1001 0100\$3C0
23732 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23733 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23734 \ -- \ID input divider \ 10 = /4
23735 \ -- \MC Mode Control \ 01 = up to TB0CCR0
23736 \ - \TBCLR TimerB Clear
23739 \ --------------------------------\\
23740 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23741 \ -- \CM Capture Mode
23746 \ --- \OUTMOD \ 011 = set/reset
23752 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
23754 \ ------------------------------\
23755 \ set TimerB to make 50kHz PWM \
23756 \ ------------------------------\
23757 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23758 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
23759 \ ------------------------------\
23760 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
23761 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
23762 \ ------------------------------\
23763 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23764 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
23765 \ ------------------------------\
23766 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23767 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
23768 \ ------------------------------\
23769 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
23770 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
23771 \ ------------------------------\
23772 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
23773 \ ------------------------------\
23774 \ set TimerB to generate PWM for LCD_Vo
23775 \ ------------------------------\
23776 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
23777 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
23778 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23779 \ ------------------------------\
23780 BIS.B #LCDVo,&LCDVo_DIR \
23781 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
23782 \ ------------------------------\
23783 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23784 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23785 \ ------------------------------\
23786 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23787 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23788 \ ------------------------------\
23789 \ WDT interval init part \
23790 \ ------------------------------\
23791 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
23792 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
23793 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
23794 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
23795 \ ------------------------------\
23797 \ ------------------------------\
23798 BIS.B #RC5,&IR_IE \ enable RC5_Int
23799 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23800 \ ------------------------------\
23801 \ init interrupt vectors
23802 \ ------------------------------\
23803 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
23804 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23805 \ ------------------------------\
23806 \ define LPM mode for ACCEPT \
23807 \ ------------------------------\
23808 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23809 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23810 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23812 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
23814 \ ------------------------------\
23816 \ ------------------------------\
23817 $03E8 20_US \ 1- wait 20 ms
23818 $03 TOP_LCD \ 2- send DB5=DB4=1
23819 $CD 20_US \ 3- wait 4,1 ms
23820 $03 TOP_LCD \ 4- send again DB5=DB4=1
23821 $5 20_US \ 5- wait 0,1 ms
23822 $03 TOP_LCD \ 6- send again again DB5=DB4=1
23823 $2 20_US \ wait 40 us = LCD cycle
23824 $02 TOP_LCD \ 7- send DB5=1 DB4=0
23825 $2 20_US \ wait 40 us = LCD cycle
23826 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23827 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23828 LCD_Clear \ 10- "LCD_Clear"
23829 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23830 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23831 LCD_Clear \ 10- "LCD_Clear"
23832 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23833 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23835 ['] (CR) IS CR \ ' (CR) is CR
23836 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
23838 ." RC5toLCD is running. Type STOP to quit"
23839 \ NOECHO \ uncomment to run this app without terminal connexion
23840 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
23841 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
23845 : STOP \ stops multitasking, must to be used before downloading app
23846 ['] (WARM) IS WARM \ remove START app from FORTH init process
23847 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
23855 CODE MAX \ n1 n2 -- n3 signed maximum
23856 CMP @PSP,TOS \ n2-n1
23857 S< ?GOTO FW1 \ n2<n1
23863 CODE MIN \ n1 n2 -- n3 signed minimum
23864 CMP @PSP,TOS \ n2-n1
23865 S< ?GOTO BW1 \ n2<n1
23871 : U.R \ u n -- display u unsigned in n width (n >= 2)
23873 R> OVER - 0 MAX SPACES TYPE
23877 CODE 20_US \ n -- n * 20 us
23878 BEGIN \ 3 cycles loop + 6~
23879 \ MOV #5,W \ 3 MCLK = 1 MHz
23880 \ MOV #23,W \ 3 MCLK = 4 MHz
23881 MOV #51,W \ 3 MCLK = 8 MHz
23882 \ MOV #104,W \ 3 MCLK = 16 MHz
23883 \ MOV #158,W \ 3 MCLK = 24 MHz
23884 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
23894 CODE TOP_LCD \ LCD Sample
23895 \ \ if write : %xxxxWWWW --
23896 \ \ if read : -- %0000RRRR
23897 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23898 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23899 0= IF \ write LCD bits pattern
23900 AND.B #LCD_DB,TOS \
23901 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23902 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23905 THEN \ read LCD bits pattern
23908 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23909 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23910 AND.B #LCD_DB,TOS \
23915 CODE LCD_W \ byte -- write byte to LCD
23917 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
23918 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
23919 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23920 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23921 COLON \ high level word starts here
23922 TOP_LCD 2 20_US \ write high nibble first
23927 CODE LCD_WrC \ char -- Write Char
23928 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23933 CODE LCD_WrF \ func -- Write Fonction
23934 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23940 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
23945 $02 LCD_WrF 100 20_us
23949 \ : LCD_Entry_set $04 OR LCD_WrF ;
23951 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
23953 \ : LCD_Display_Shift $10 OR LCD_WrF ;
23955 \ : LCD_Fn_Set $20 OR LCD_WrF ;
23957 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
23959 \ : LCD_Goto $80 OR LCD_WrF ;
23961 \ CODE LCD_R \ -- byte read byte from LCD
23962 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23963 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23964 \ COLON \ starts a FORTH word
23965 \ TOP_LCD 2 20_us \ -- %0000HHHH
23966 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
23967 \ HI2LO \ switch from FORTH to assembler
23968 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
23969 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
23970 \ MOV @RSP+,IP \ restore IP saved by COLON
23975 \ CODE LCD_RdS \ -- status Read Status
23976 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23981 \ CODE LCD_RdC \ -- char Read Char
23982 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23987 \ -------------+------+------+------+------++---+---+---+---+---------+
23988 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
23989 \ -------------+------+------+------+------++---+---+---+---+---------+
23990 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
23991 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
23992 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
23993 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
23994 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
23995 \ -------------+------+------+------+------++---+---+---+---+---------+
23998 \ ******************************\
23999 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24000 \ ******************************\
24001 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
24002 \ ------------------------------\
24003 \ define LPM mode for ACCEPT \
24004 \ ------------------------------\
24005 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24006 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24007 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24008 BIT.B #SW2,&SW2_IN \ test switch S2
24009 0= IF \ case of switch S2 pressed
24010 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
24012 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
24015 BIT.B #SW1,&SW1_IN \ test switch S1 input
24016 0= IF \ case of Switch S1 pressed
24017 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
24019 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
24023 RETI \ CPU is ON, GIE is OFF
24028 \ ------------------------------\
24029 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24030 \ ******************************\
24031 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24032 \ ******************************\
24033 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24034 \ \ SMclock = 8|16|24 MHz
24035 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
24036 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
24037 \ \ SR(9)=new Toggle bit memory (ADD on)
24038 \ ------------------------------\
24039 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
24040 \ ------------------------------\
24041 \ define LPM mode for ACCEPT \
24042 \ ------------------------------\
24043 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24044 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24045 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24046 \ ------------------------------\
24047 \ RC5_FirstStartBitHalfCycle: \
24048 \ ------------------------------\
24049 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
24050 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
24051 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
24052 MOV #1778,X \ RC5_Period in us
24053 MOV #14,W \ count of loop
24055 \ ------------------------------\
24056 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
24057 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
24058 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
24059 \ RC5_Compute_3/4_Period: \ |
24060 RRUM #1,X \ X=1/2 cycle |
24064 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
24065 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
24067 \ ------------------------------\
24068 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
24069 \ ------------------------------\
24070 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24071 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
24072 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24073 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24074 SUB #1,W \ decrement count loop
24075 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
24076 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24077 0<> WHILE \ ----> out of loop ----+
24078 \ RC5_compute_7/4_Time_out: \ |
24079 ADD X,Y \ | out of bound = 7/4 period
24080 \ RC5_WaitHalfCycleP1.2_IFG: \ |
24082 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
24083 0>= IF \ | if cycle time out of bound
24084 BIC #$30,&TA0CTL \ | stop timer_A0
24085 RETI \ | then quit to do nothing
24087 \ ------------------------------\ |
24088 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
24090 MOV &TA0R,X \ | | get new RC5_period value
24091 REPEAT \ ----> loop back --+ |
24092 \ ------------------------------\ |
24093 \ RC5_SampleEndOf: \ <---------------------+
24094 \ ------------------------------\
24095 BIC #$30,&TA0CTL \ stop timer_A0
24096 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
24097 \ ******************************\
24098 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24099 \ ******************************\
24100 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
24101 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
24102 XOR IP,X \ (new XOR old) Toggle bit (13)
24103 BIT #BIT13,X \ X(13) = New_RC5_command
24104 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
24106 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
24107 \ ******************************\
24108 \ RC5_ComputeNewRC5word \
24109 \ ******************************\
24111 MOV &BASE,2(PSP) \ save variable BASE before use
24112 MOV TOS,0(PSP) \ save TOS before use
24113 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
24114 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
24115 \ ******************************\
24116 \ RC5_ComputeC6bit \
24117 \ ******************************\
24118 BIT #$4000,IP \ test /C6 bit in IP
24119 0= IF BIS #$40,TOS \ set C6 bit in S
24120 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
24121 \ ******************************\
24122 \ RC5_CommandByteIsDone \ RC5_code --
24123 \ ******************************\
24125 \ ------------------------------\
24126 \ Display IR_RC5 code \
24127 \ ------------------------------\
24128 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
24129 \ ------------------------------\
24130 LO2HI \ switch from assembler to FORTH
24131 ['] LCD_CLEAR IS CR \ redirects CR
24132 ['] LCD_WrC IS EMIT \ redirects EMIT
24133 $10 BASE ! \ change BASE to hexadecimal
24134 CR ." $" 2 U.R \ print IR_RC5 code
24135 ['] (CR) IS CR \ restore CR
24136 ['] (EMIT) IS EMIT \ restore EMIT
24137 HI2LO \ switch from FORTH to assembler
24138 \ ------------------------------\
24139 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
24140 \ ------------------------------\
24141 MOV @PSP+,&BASE \ restore variable BASE
24142 RETI \ CPU is ON, GIE is OFF
24147 \ ------------------------------\
24148 \ TB0CTL = %0000 0010 1001 0100\$3C0
24149 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24150 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24151 \ -- \ID input divider \ 10 = /4
24152 \ -- \MC Mode Control \ 01 = up to TB0CCR0
24153 \ - \TBCLR TimerB Clear
24156 \ --------------------------------\\
24157 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24158 \ -- \CM Capture Mode
24163 \ --- \OUTMOD \ 011 = set/reset
24169 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
24171 \ ------------------------------\
24172 \ set TimerB to make 50kHz PWM \
24173 \ ------------------------------\
24174 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24175 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
24176 \ ------------------------------\
24177 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24178 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
24179 \ ------------------------------\
24180 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24181 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
24182 \ ------------------------------\
24183 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24184 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
24185 \ ------------------------------\
24186 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24187 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
24188 \ ------------------------------\
24189 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
24190 \ ------------------------------\
24191 \ set TimerB to generate PWM for LCD_Vo
24192 \ ------------------------------\
24193 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
24194 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
24195 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24196 \ ------------------------------\
24197 BIS.B #LCDVo,&LCDVo_DIR \
24198 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
24199 \ ------------------------------\
24200 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24201 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24202 \ ------------------------------\
24203 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24204 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24205 \ ------------------------------\
24206 \ WDT interval init part \
24207 \ ------------------------------\
24208 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
24209 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
24210 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
24211 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
24212 \ ------------------------------\
24214 \ ------------------------------\
24215 BIS.B #RC5,&IR_IE \ enable RC5_Int
24216 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24217 \ ------------------------------\
24218 \ init interrupt vectors
24219 \ ------------------------------\
24220 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
24221 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24222 \ ------------------------------\
24223 \ define LPM mode for ACCEPT \
24224 \ ------------------------------\
24225 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24226 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24227 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24229 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
24231 \ ------------------------------\
24233 \ ------------------------------\
24234 $03E8 20_US \ 1- wait 20 ms
24235 $03 TOP_LCD \ 2- send DB5=DB4=1
24236 $CD 20_US \ 3- wait 4,1 ms
24237 $03 TOP_LCD \ 4- send again DB5=DB4=1
24238 $5 20_US \ 5- wait 0,1 ms
24239 $03 TOP_LCD \ 6- send again again DB5=DB4=1
24240 $2 20_US \ wait 40 us = LCD cycle
24241 $02 TOP_LCD \ 7- send DB5=1 DB4=0
24242 $2 20_US \ wait 40 us = LCD cycle
24243 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24244 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24245 LCD_Clear \ 10- "LCD_Clear"
24246 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24247 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24248 LCD_Clear \ 10- "LCD_Clear"
24249 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24250 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24252 ['] (CR) IS CR \ ' (CR) is CR
24253 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
24255 ." RC5toLCD is running. Type STOP to quit"
24256 \ NOECHO \ uncomment to run this app without terminal connexion
24257 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
24258 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
24262 : STOP \ stops multitasking, must to be used before downloading app
24263 ['] (WARM) IS WARM \ remove START app from FORTH init process
24264 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
24272 CODE MAX \ n1 n2 -- n3 signed maximum
24273 CMP @PSP,TOS \ n2-n1
24274 S< ?GOTO FW1 \ n2<n1
24280 CODE MIN \ n1 n2 -- n3 signed minimum
24281 CMP @PSP,TOS \ n2-n1
24282 S< ?GOTO BW1 \ n2<n1
24288 : U.R \ u n -- display u unsigned in n width (n >= 2)
24290 R> OVER - 0 MAX SPACES TYPE
24294 CODE 20_US \ n -- n * 20 us
24295 BEGIN \ 3 cycles loop + 6~
24296 \ MOV #5,W \ 3 MCLK = 1 MHz
24297 \ MOV #23,W \ 3 MCLK = 4 MHz
24298 MOV #51,W \ 3 MCLK = 8 MHz
24299 \ MOV #104,W \ 3 MCLK = 16 MHz
24300 \ MOV #158,W \ 3 MCLK = 24 MHz
24301 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
24311 CODE TOP_LCD \ LCD Sample
24312 \ \ if write : %xxxxWWWW --
24313 \ \ if read : -- %0000RRRR
24314 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24315 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24316 0= IF \ write LCD bits pattern
24317 AND.B #LCD_DB,TOS \
24318 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24319 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24322 THEN \ read LCD bits pattern
24325 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24326 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24327 AND.B #LCD_DB,TOS \
24332 CODE LCD_W \ byte -- write byte to LCD
24334 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24335 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24336 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24337 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24338 COLON \ high level word starts here
24339 TOP_LCD 2 20_US \ write high nibble first
24344 CODE LCD_WrC \ char -- Write Char
24345 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24350 CODE LCD_WrF \ func -- Write Fonction
24351 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24357 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
24362 $02 LCD_WrF 100 20_us
24366 \ : LCD_Entry_set $04 OR LCD_WrF ;
24368 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
24370 \ : LCD_Display_Shift $10 OR LCD_WrF ;
24372 \ : LCD_Fn_Set $20 OR LCD_WrF ;
24374 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
24376 \ : LCD_Goto $80 OR LCD_WrF ;
24378 \ CODE LCD_R \ -- byte read byte from LCD
24379 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24380 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24381 \ COLON \ starts a FORTH word
24382 \ TOP_LCD 2 20_us \ -- %0000HHHH
24383 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
24384 \ HI2LO \ switch from FORTH to assembler
24385 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
24386 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
24387 \ MOV @RSP+,IP \ restore IP saved by COLON
24392 \ CODE LCD_RdS \ -- status Read Status
24393 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24398 \ CODE LCD_RdC \ -- char Read Char
24399 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24404 \ -------------+------+------+------+------++---+---+---+---+---------+
24405 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
24406 \ -------------+------+------+------+------++---+---+---+---+---------+
24407 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
24408 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
24409 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
24410 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
24411 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
24412 \ -------------+------+------+------+------++---+---+---+---+---------+
24415 \ ******************************\
24416 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24417 \ ******************************\
24418 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
24419 \ ------------------------------\
24420 \ define LPM mode for ACCEPT \
24421 \ ------------------------------\
24422 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24423 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24424 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24425 BIT.B #SW2,&SW2_IN \ test switch S2
24426 0= IF \ case of switch S2 pressed
24427 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
24429 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
24432 BIT.B #SW1,&SW1_IN \ test switch S1 input
24433 0= IF \ case of Switch S1 pressed
24434 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
24436 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
24440 RETI \ CPU is ON, GIE is OFF
24445 \ ------------------------------\
24446 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24447 \ ******************************\
24448 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24449 \ ******************************\
24450 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24451 \ \ SMclock = 8|16|24 MHz
24452 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
24453 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
24454 \ \ SR(9)=new Toggle bit memory (ADD on)
24455 \ ------------------------------\
24456 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
24457 \ ------------------------------\
24458 \ define LPM mode for ACCEPT \
24459 \ ------------------------------\
24460 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24461 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24462 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24463 \ ------------------------------\
24464 \ RC5_FirstStartBitHalfCycle: \
24465 \ ------------------------------\
24466 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
24467 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
24468 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
24469 MOV #1778,X \ RC5_Period in us
24470 MOV #14,W \ count of loop
24472 \ ------------------------------\
24473 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
24474 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
24475 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
24476 \ RC5_Compute_3/4_Period: \ |
24477 RRUM #1,X \ X=1/2 cycle |
24481 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
24482 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
24484 \ ------------------------------\
24485 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
24486 \ ------------------------------\
24487 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24488 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
24489 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24490 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24491 SUB #1,W \ decrement count loop
24492 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
24493 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24494 0<> WHILE \ ----> out of loop ----+
24495 \ RC5_compute_7/4_Time_out: \ |
24496 ADD X,Y \ | out of bound = 7/4 period
24497 \ RC5_WaitHalfCycleP1.2_IFG: \ |
24499 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
24500 0>= IF \ | if cycle time out of bound
24501 BIC #$30,&TA0CTL \ | stop timer_A0
24502 RETI \ | then quit to do nothing
24504 \ ------------------------------\ |
24505 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
24507 MOV &TA0R,X \ | | get new RC5_period value
24508 REPEAT \ ----> loop back --+ |
24509 \ ------------------------------\ |
24510 \ RC5_SampleEndOf: \ <---------------------+
24511 \ ------------------------------\
24512 BIC #$30,&TA0CTL \ stop timer_A0
24513 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
24514 \ ******************************\
24515 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24516 \ ******************************\
24517 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
24518 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
24519 XOR IP,X \ (new XOR old) Toggle bit (13)
24520 BIT #BIT13,X \ X(13) = New_RC5_command
24521 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
24523 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
24524 \ ******************************\
24525 \ RC5_ComputeNewRC5word \
24526 \ ******************************\
24528 MOV &BASE,2(PSP) \ save variable BASE before use
24529 MOV TOS,0(PSP) \ save TOS before use
24530 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
24531 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
24532 \ ******************************\
24533 \ RC5_ComputeC6bit \
24534 \ ******************************\
24535 BIT #$4000,IP \ test /C6 bit in IP
24536 0= IF BIS #$40,TOS \ set C6 bit in S
24537 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
24538 \ ******************************\
24539 \ RC5_CommandByteIsDone \ RC5_code --
24540 \ ******************************\
24542 \ ------------------------------\
24543 \ Display IR_RC5 code \
24544 \ ------------------------------\
24545 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
24546 \ ------------------------------\
24547 LO2HI \ switch from assembler to FORTH
24548 ['] LCD_CLEAR IS CR \ redirects CR
24549 ['] LCD_WrC IS EMIT \ redirects EMIT
24550 $10 BASE ! \ change BASE to hexadecimal
24551 CR ." $" 2 U.R \ print IR_RC5 code
24552 ['] (CR) IS CR \ restore CR
24553 ['] (EMIT) IS EMIT \ restore EMIT
24554 HI2LO \ switch from FORTH to assembler
24555 \ ------------------------------\
24556 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
24557 \ ------------------------------\
24558 MOV @PSP+,&BASE \ restore variable BASE
24559 RETI \ CPU is ON, GIE is OFF
24564 \ ------------------------------\
24565 \ TB0CTL = %0000 0010 1001 0100\$3C0
24566 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24567 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24568 \ -- \ID input divider \ 10 = /4
24569 \ -- \MC Mode Control \ 01 = up to TB0CCR0
24570 \ - \TBCLR TimerB Clear
24573 \ --------------------------------\\
24574 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24575 \ -- \CM Capture Mode
24580 \ --- \OUTMOD \ 011 = set/reset
24586 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
24588 \ ------------------------------\
24589 \ set TimerB to make 50kHz PWM \
24590 \ ------------------------------\
24591 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24592 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
24593 \ ------------------------------\
24594 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
24595 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
24596 \ ------------------------------\
24597 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24598 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
24599 \ ------------------------------\
24600 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24601 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
24602 \ ------------------------------\
24603 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
24604 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
24605 \ ------------------------------\
24606 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
24607 \ ------------------------------\
24608 \ set TimerB to generate PWM for LCD_Vo
24609 \ ------------------------------\
24610 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
24611 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
24612 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24613 \ ------------------------------\
24614 BIS.B #LCDVo,&LCDVo_DIR \
24615 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
24616 \ ------------------------------\
24617 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24618 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24619 \ ------------------------------\
24620 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24621 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24622 \ ------------------------------\
24623 \ WDT interval init part \
24624 \ ------------------------------\
24625 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
24626 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
24627 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
24628 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
24629 \ ------------------------------\
24631 \ ------------------------------\
24632 BIS.B #RC5,&IR_IE \ enable RC5_Int
24633 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24634 \ ------------------------------\
24635 \ init interrupt vectors
24636 \ ------------------------------\
24637 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
24638 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24639 \ ------------------------------\
24640 \ define LPM mode for ACCEPT \
24641 \ ------------------------------\
24642 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24643 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24644 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24646 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
24648 \ ------------------------------\
24650 \ ------------------------------\
24651 $03E8 20_US \ 1- wait 20 ms
24652 $03 TOP_LCD \ 2- send DB5=DB4=1
24653 $CD 20_US \ 3- wait 4,1 ms
24654 $03 TOP_LCD \ 4- send again DB5=DB4=1
24655 $5 20_US \ 5- wait 0,1 ms
24656 $03 TOP_LCD \ 6- send again again DB5=DB4=1
24657 $2 20_US \ wait 40 us = LCD cycle
24658 $02 TOP_LCD \ 7- send DB5=1 DB4=0
24659 $2 20_US \ wait 40 us = LCD cycle
24660 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24661 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24662 LCD_Clear \ 10- "LCD_Clear"
24663 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24664 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24665 LCD_Clear \ 10- "LCD_Clear"
24666 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24667 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24669 ['] (CR) IS CR \ ' (CR) is CR
24670 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
24672 ." RC5toLCD is running. Type STOP to quit"
24673 \ NOECHO \ uncomment to run this app without terminal connexion
24674 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
24675 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
24679 : STOP \ stops multitasking, must to be used before downloading app
24680 ['] (WARM) IS WARM \ remove START app from FORTH init process
24681 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
24689 CODE MAX \ n1 n2 -- n3 signed maximum
24690 CMP @PSP,TOS \ n2-n1
24691 S< ?GOTO FW1 \ n2<n1
24697 CODE MIN \ n1 n2 -- n3 signed minimum
24698 CMP @PSP,TOS \ n2-n1
24699 S< ?GOTO BW1 \ n2<n1
24705 : U.R \ u n -- display u unsigned in n width (n >= 2)
24707 R> OVER - 0 MAX SPACES TYPE
24711 CODE 20_US \ n -- n * 20 us
24712 BEGIN \ 3 cycles loop + 6~
24713 \ MOV #5,W \ 3 MCLK = 1 MHz
24714 \ MOV #23,W \ 3 MCLK = 4 MHz
24715 MOV #51,W \ 3 MCLK = 8 MHz
24716 \ MOV #104,W \ 3 MCLK = 16 MHz
24717 \ MOV #158,W \ 3 MCLK = 24 MHz
24718 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
24728 CODE TOP_LCD \ LCD Sample
24729 \ \ if write : %xxxxWWWW --
24730 \ \ if read : -- %0000RRRR
24731 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24732 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24733 0= IF \ write LCD bits pattern
24734 AND.B #LCD_DB,TOS \
24735 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24736 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24739 THEN \ read LCD bits pattern
24742 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24743 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24744 AND.B #LCD_DB,TOS \
24749 CODE LCD_W \ byte -- write byte to LCD
24751 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
24752 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
24753 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24754 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24755 COLON \ high level word starts here
24756 TOP_LCD 2 20_US \ write high nibble first
24761 CODE LCD_WrC \ char -- Write Char
24762 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24767 CODE LCD_WrF \ func -- Write Fonction
24768 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24774 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
24779 $02 LCD_WrF 100 20_us
24783 \ : LCD_Entry_set $04 OR LCD_WrF ;
24785 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
24787 \ : LCD_Display_Shift $10 OR LCD_WrF ;
24789 \ : LCD_Fn_Set $20 OR LCD_WrF ;
24791 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
24793 \ : LCD_Goto $80 OR LCD_WrF ;
24795 \ CODE LCD_R \ -- byte read byte from LCD
24796 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24797 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24798 \ COLON \ starts a FORTH word
24799 \ TOP_LCD 2 20_us \ -- %0000HHHH
24800 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
24801 \ HI2LO \ switch from FORTH to assembler
24802 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
24803 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
24804 \ MOV @RSP+,IP \ restore IP saved by COLON
24809 \ CODE LCD_RdS \ -- status Read Status
24810 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24815 \ CODE LCD_RdC \ -- char Read Char
24816 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24821 \ -------------+------+------+------+------++---+---+---+---+---------+
24822 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
24823 \ -------------+------+------+------+------++---+---+---+---+---------+
24824 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
24825 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
24826 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
24827 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
24828 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
24829 \ -------------+------+------+------+------++---+---+---+---+---------+
24832 \ ******************************\
24833 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24834 \ ******************************\
24835 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
24836 \ ------------------------------\
24837 \ define LPM mode for ACCEPT \
24838 \ ------------------------------\
24839 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24840 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24841 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24842 BIT.B #SW2,&SW2_IN \ test switch S2
24843 0= IF \ case of switch S2 pressed
24844 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
24846 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
24849 BIT.B #SW1,&SW1_IN \ test switch S1 input
24850 0= IF \ case of Switch S1 pressed
24851 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
24853 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
24857 RETI \ CPU is ON, GIE is OFF
24862 \ ------------------------------\
24863 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24864 \ ******************************\
24865 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24866 \ ******************************\
24867 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24868 \ \ SMclock = 8|16|24 MHz
24869 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
24870 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
24871 \ \ SR(9)=new Toggle bit memory (ADD on)
24872 \ ------------------------------\
24873 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
24874 \ ------------------------------\
24875 \ define LPM mode for ACCEPT \
24876 \ ------------------------------\
24877 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24878 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24879 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24880 \ ------------------------------\
24881 \ RC5_FirstStartBitHalfCycle: \
24882 \ ------------------------------\
24883 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
24884 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
24885 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
24886 MOV #1778,X \ RC5_Period in us
24887 MOV #14,W \ count of loop
24889 \ ------------------------------\
24890 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
24891 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
24892 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
24893 \ RC5_Compute_3/4_Period: \ |
24894 RRUM #1,X \ X=1/2 cycle |
24898 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
24899 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
24901 \ ------------------------------\
24902 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
24903 \ ------------------------------\
24904 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24905 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
24906 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24907 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24908 SUB #1,W \ decrement count loop
24909 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
24910 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24911 0<> WHILE \ ----> out of loop ----+
24912 \ RC5_compute_7/4_Time_out: \ |
24913 ADD X,Y \ | out of bound = 7/4 period
24914 \ RC5_WaitHalfCycleP1.2_IFG: \ |
24916 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
24917 0>= IF \ | if cycle time out of bound
24918 BIC #$30,&TA0CTL \ | stop timer_A0
24919 RETI \ | then quit to do nothing
24921 \ ------------------------------\ |
24922 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
24924 MOV &TA0R,X \ | | get new RC5_period value
24925 REPEAT \ ----> loop back --+ |
24926 \ ------------------------------\ |
24927 \ RC5_SampleEndOf: \ <---------------------+
24928 \ ------------------------------\
24929 BIC #$30,&TA0CTL \ stop timer_A0
24930 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
24931 \ ******************************\
24932 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24933 \ ******************************\
24934 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
24935 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
24936 XOR IP,X \ (new XOR old) Toggle bit (13)
24937 BIT #BIT13,X \ X(13) = New_RC5_command
24938 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
24940 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
24941 \ ******************************\
24942 \ RC5_ComputeNewRC5word \
24943 \ ******************************\
24945 MOV &BASE,2(PSP) \ save variable BASE before use
24946 MOV TOS,0(PSP) \ save TOS before use
24947 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
24948 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
24949 \ ******************************\
24950 \ RC5_ComputeC6bit \
24951 \ ******************************\
24952 BIT #$4000,IP \ test /C6 bit in IP
24953 0= IF BIS #$40,TOS \ set C6 bit in S
24954 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
24955 \ ******************************\
24956 \ RC5_CommandByteIsDone \ RC5_code --
24957 \ ******************************\
24959 \ ------------------------------\
24960 \ Display IR_RC5 code \
24961 \ ------------------------------\
24962 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
24963 \ ------------------------------\
24964 LO2HI \ switch from assembler to FORTH
24965 ['] LCD_CLEAR IS CR \ redirects CR
24966 ['] LCD_WrC IS EMIT \ redirects EMIT
24967 $10 BASE ! \ change BASE to hexadecimal
24968 CR ." $" 2 U.R \ print IR_RC5 code
24969 ['] (CR) IS CR \ restore CR
24970 ['] (EMIT) IS EMIT \ restore EMIT
24971 HI2LO \ switch from FORTH to assembler
24972 \ ------------------------------\
24973 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
24974 \ ------------------------------\
24975 MOV @PSP+,&BASE \ restore variable BASE
24976 RETI \ CPU is ON, GIE is OFF
24981 \ ------------------------------\
24982 \ TB0CTL = %0000 0010 1001 0100\$3C0
24983 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24984 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24985 \ -- \ID input divider \ 10 = /4
24986 \ -- \MC Mode Control \ 01 = up to TB0CCR0
24987 \ - \TBCLR TimerB Clear
24990 \ --------------------------------\\
24991 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24992 \ -- \CM Capture Mode
24997 \ --- \OUTMOD \ 011 = set/reset
25003 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
25005 \ ------------------------------\
25006 \ set TimerB to make 50kHz PWM \
25007 \ ------------------------------\
25008 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25009 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
25010 \ ------------------------------\
25011 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25012 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
25013 \ ------------------------------\
25014 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25015 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
25016 \ ------------------------------\
25017 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25018 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
25019 \ ------------------------------\
25020 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25021 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
25022 \ ------------------------------\
25023 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
25024 \ ------------------------------\
25025 \ set TimerB to generate PWM for LCD_Vo
25026 \ ------------------------------\
25027 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
25028 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
25029 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25030 \ ------------------------------\
25031 BIS.B #LCDVo,&LCDVo_DIR \
25032 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
25033 \ ------------------------------\
25034 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25035 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25036 \ ------------------------------\
25037 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25038 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25039 \ ------------------------------\
25040 \ WDT interval init part \
25041 \ ------------------------------\
25042 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
25043 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
25044 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
25045 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
25046 \ ------------------------------\
25048 \ ------------------------------\
25049 BIS.B #RC5,&IR_IE \ enable RC5_Int
25050 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25051 \ ------------------------------\
25052 \ init interrupt vectors
25053 \ ------------------------------\
25054 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
25055 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25056 \ ------------------------------\
25057 \ define LPM mode for ACCEPT \
25058 \ ------------------------------\
25059 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25060 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25061 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25063 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
25065 \ ------------------------------\
25067 \ ------------------------------\
25068 $03E8 20_US \ 1- wait 20 ms
25069 $03 TOP_LCD \ 2- send DB5=DB4=1
25070 $CD 20_US \ 3- wait 4,1 ms
25071 $03 TOP_LCD \ 4- send again DB5=DB4=1
25072 $5 20_US \ 5- wait 0,1 ms
25073 $03 TOP_LCD \ 6- send again again DB5=DB4=1
25074 $2 20_US \ wait 40 us = LCD cycle
25075 $02 TOP_LCD \ 7- send DB5=1 DB4=0
25076 $2 20_US \ wait 40 us = LCD cycle
25077 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25078 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25079 LCD_Clear \ 10- "LCD_Clear"
25080 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25081 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25082 LCD_Clear \ 10- "LCD_Clear"
25083 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25084 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25086 ['] (CR) IS CR \ ' (CR) is CR
25087 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
25089 ." RC5toLCD is running. Type STOP to quit"
25090 \ NOECHO \ uncomment to run this app without terminal connexion
25091 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
25092 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
25096 : STOP \ stops multitasking, must to be used before downloading app
25097 ['] (WARM) IS WARM \ remove START app from FORTH init process
25098 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
25106 CODE MAX \ n1 n2 -- n3 signed maximum
25107 CMP @PSP,TOS \ n2-n1
25108 S< ?GOTO FW1 \ n2<n1
25114 CODE MIN \ n1 n2 -- n3 signed minimum
25115 CMP @PSP,TOS \ n2-n1
25116 S< ?GOTO BW1 \ n2<n1
25122 : U.R \ u n -- display u unsigned in n width (n >= 2)
25124 R> OVER - 0 MAX SPACES TYPE
25128 CODE 20_US \ n -- n * 20 us
25129 BEGIN \ 3 cycles loop + 6~
25130 \ MOV #5,W \ 3 MCLK = 1 MHz
25131 \ MOV #23,W \ 3 MCLK = 4 MHz
25132 MOV #51,W \ 3 MCLK = 8 MHz
25133 \ MOV #104,W \ 3 MCLK = 16 MHz
25134 \ MOV #158,W \ 3 MCLK = 24 MHz
25135 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
25145 CODE TOP_LCD \ LCD Sample
25146 \ \ if write : %xxxxWWWW --
25147 \ \ if read : -- %0000RRRR
25148 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25149 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25150 0= IF \ write LCD bits pattern
25151 AND.B #LCD_DB,TOS \
25152 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25153 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25156 THEN \ read LCD bits pattern
25159 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25160 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25161 AND.B #LCD_DB,TOS \
25166 CODE LCD_W \ byte -- write byte to LCD
25168 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
25169 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
25170 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25171 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25172 COLON \ high level word starts here
25173 TOP_LCD 2 20_US \ write high nibble first
25178 CODE LCD_WrC \ char -- Write Char
25179 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25184 CODE LCD_WrF \ func -- Write Fonction
25185 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25191 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
25196 $02 LCD_WrF 100 20_us
25200 \ : LCD_Entry_set $04 OR LCD_WrF ;
25202 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
25204 \ : LCD_Display_Shift $10 OR LCD_WrF ;
25206 \ : LCD_Fn_Set $20 OR LCD_WrF ;
25208 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
25210 \ : LCD_Goto $80 OR LCD_WrF ;
25212 \ CODE LCD_R \ -- byte read byte from LCD
25213 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25214 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25215 \ COLON \ starts a FORTH word
25216 \ TOP_LCD 2 20_us \ -- %0000HHHH
25217 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25218 \ HI2LO \ switch from FORTH to assembler
25219 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25220 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25221 \ MOV @RSP+,IP \ restore IP saved by COLON
25226 \ CODE LCD_RdS \ -- status Read Status
25227 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25232 \ CODE LCD_RdC \ -- char Read Char
25233 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25238 \ -------------+------+------+------+------++---+---+---+---+---------+
25239 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
25240 \ -------------+------+------+------+------++---+---+---+---+---------+
25241 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
25242 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
25243 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
25244 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
25245 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
25246 \ -------------+------+------+------+------++---+---+---+---+---------+
25249 \ ******************************\
25250 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25251 \ ******************************\
25252 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
25253 \ ------------------------------\
25254 \ define LPM mode for ACCEPT \
25255 \ ------------------------------\
25256 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25257 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25258 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25259 BIT.B #SW2,&SW2_IN \ test switch S2
25260 0= IF \ case of switch S2 pressed
25261 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
25263 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
25266 BIT.B #SW1,&SW1_IN \ test switch S1 input
25267 0= IF \ case of Switch S1 pressed
25268 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
25270 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
25274 RETI \ CPU is ON, GIE is OFF
25279 \ ------------------------------\
25280 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25281 \ ******************************\
25282 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25283 \ ******************************\
25284 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25285 \ \ SMclock = 8|16|24 MHz
25286 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
25287 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
25288 \ \ SR(9)=new Toggle bit memory (ADD on)
25289 \ ------------------------------\
25290 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
25291 \ ------------------------------\
25292 \ define LPM mode for ACCEPT \
25293 \ ------------------------------\
25294 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25295 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25296 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25297 \ ------------------------------\
25298 \ RC5_FirstStartBitHalfCycle: \
25299 \ ------------------------------\
25300 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
25301 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
25302 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
25303 MOV #1778,X \ RC5_Period in us
25304 MOV #14,W \ count of loop
25306 \ ------------------------------\
25307 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
25308 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
25309 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
25310 \ RC5_Compute_3/4_Period: \ |
25311 RRUM #1,X \ X=1/2 cycle |
25315 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
25316 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
25318 \ ------------------------------\
25319 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
25320 \ ------------------------------\
25321 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25322 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
25323 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25324 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25325 SUB #1,W \ decrement count loop
25326 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
25327 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25328 0<> WHILE \ ----> out of loop ----+
25329 \ RC5_compute_7/4_Time_out: \ |
25330 ADD X,Y \ | out of bound = 7/4 period
25331 \ RC5_WaitHalfCycleP1.2_IFG: \ |
25333 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
25334 0>= IF \ | if cycle time out of bound
25335 BIC #$30,&TA0CTL \ | stop timer_A0
25336 RETI \ | then quit to do nothing
25338 \ ------------------------------\ |
25339 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
25341 MOV &TA0R,X \ | | get new RC5_period value
25342 REPEAT \ ----> loop back --+ |
25343 \ ------------------------------\ |
25344 \ RC5_SampleEndOf: \ <---------------------+
25345 \ ------------------------------\
25346 BIC #$30,&TA0CTL \ stop timer_A0
25347 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
25348 \ ******************************\
25349 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25350 \ ******************************\
25351 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
25352 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
25353 XOR IP,X \ (new XOR old) Toggle bit (13)
25354 BIT #BIT13,X \ X(13) = New_RC5_command
25355 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
25357 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
25358 \ ******************************\
25359 \ RC5_ComputeNewRC5word \
25360 \ ******************************\
25362 MOV &BASE,2(PSP) \ save variable BASE before use
25363 MOV TOS,0(PSP) \ save TOS before use
25364 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
25365 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
25366 \ ******************************\
25367 \ RC5_ComputeC6bit \
25368 \ ******************************\
25369 BIT #$4000,IP \ test /C6 bit in IP
25370 0= IF BIS #$40,TOS \ set C6 bit in S
25371 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
25372 \ ******************************\
25373 \ RC5_CommandByteIsDone \ RC5_code --
25374 \ ******************************\
25376 \ ------------------------------\
25377 \ Display IR_RC5 code \
25378 \ ------------------------------\
25379 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
25380 \ ------------------------------\
25381 LO2HI \ switch from assembler to FORTH
25382 ['] LCD_CLEAR IS CR \ redirects CR
25383 ['] LCD_WrC IS EMIT \ redirects EMIT
25384 $10 BASE ! \ change BASE to hexadecimal
25385 CR ." $" 2 U.R \ print IR_RC5 code
25386 ['] (CR) IS CR \ restore CR
25387 ['] (EMIT) IS EMIT \ restore EMIT
25388 HI2LO \ switch from FORTH to assembler
25389 \ ------------------------------\
25390 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
25391 \ ------------------------------\
25392 MOV @PSP+,&BASE \ restore variable BASE
25393 RETI \ CPU is ON, GIE is OFF
25398 \ ------------------------------\
25399 \ TB0CTL = %0000 0010 1001 0100\$3C0
25400 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25401 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25402 \ -- \ID input divider \ 10 = /4
25403 \ -- \MC Mode Control \ 01 = up to TB0CCR0
25404 \ - \TBCLR TimerB Clear
25407 \ --------------------------------\\
25408 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25409 \ -- \CM Capture Mode
25414 \ --- \OUTMOD \ 011 = set/reset
25420 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
25422 \ ------------------------------\
25423 \ set TimerB to make 50kHz PWM \
25424 \ ------------------------------\
25425 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25426 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
25427 \ ------------------------------\
25428 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25429 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
25430 \ ------------------------------\
25431 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25432 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
25433 \ ------------------------------\
25434 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25435 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
25436 \ ------------------------------\
25437 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25438 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
25439 \ ------------------------------\
25440 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
25441 \ ------------------------------\
25442 \ set TimerB to generate PWM for LCD_Vo
25443 \ ------------------------------\
25444 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
25445 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
25446 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25447 \ ------------------------------\
25448 BIS.B #LCDVo,&LCDVo_DIR \
25449 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
25450 \ ------------------------------\
25451 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25452 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25453 \ ------------------------------\
25454 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25455 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25456 \ ------------------------------\
25457 \ WDT interval init part \
25458 \ ------------------------------\
25459 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
25460 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
25461 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
25462 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
25463 \ ------------------------------\
25465 \ ------------------------------\
25466 BIS.B #RC5,&IR_IE \ enable RC5_Int
25467 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25468 \ ------------------------------\
25469 \ init interrupt vectors
25470 \ ------------------------------\
25471 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
25472 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25473 \ ------------------------------\
25474 \ define LPM mode for ACCEPT \
25475 \ ------------------------------\
25476 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25477 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25478 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25480 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
25482 \ ------------------------------\
25484 \ ------------------------------\
25485 $03E8 20_US \ 1- wait 20 ms
25486 $03 TOP_LCD \ 2- send DB5=DB4=1
25487 $CD 20_US \ 3- wait 4,1 ms
25488 $03 TOP_LCD \ 4- send again DB5=DB4=1
25489 $5 20_US \ 5- wait 0,1 ms
25490 $03 TOP_LCD \ 6- send again again DB5=DB4=1
25491 $2 20_US \ wait 40 us = LCD cycle
25492 $02 TOP_LCD \ 7- send DB5=1 DB4=0
25493 $2 20_US \ wait 40 us = LCD cycle
25494 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25495 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25496 LCD_Clear \ 10- "LCD_Clear"
25497 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25498 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25499 LCD_Clear \ 10- "LCD_Clear"
25500 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25501 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25503 ['] (CR) IS CR \ ' (CR) is CR
25504 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
25506 ." RC5toLCD is running. Type STOP to quit"
25507 \ NOECHO \ uncomment to run this app without terminal connexion
25508 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
25509 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
25513 : STOP \ stops multitasking, must to be used before downloading app
25514 ['] (WARM) IS WARM \ remove START app from FORTH init process
25515 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
25523 CODE MAX \ n1 n2 -- n3 signed maximum
25524 CMP @PSP,TOS \ n2-n1
25525 S< ?GOTO FW1 \ n2<n1
25531 CODE MIN \ n1 n2 -- n3 signed minimum
25532 CMP @PSP,TOS \ n2-n1
25533 S< ?GOTO BW1 \ n2<n1
25539 : U.R \ u n -- display u unsigned in n width (n >= 2)
25541 R> OVER - 0 MAX SPACES TYPE
25545 CODE 20_US \ n -- n * 20 us
25546 BEGIN \ 3 cycles loop + 6~
25547 \ MOV #5,W \ 3 MCLK = 1 MHz
25548 \ MOV #23,W \ 3 MCLK = 4 MHz
25549 MOV #51,W \ 3 MCLK = 8 MHz
25550 \ MOV #104,W \ 3 MCLK = 16 MHz
25551 \ MOV #158,W \ 3 MCLK = 24 MHz
25552 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
25562 CODE TOP_LCD \ LCD Sample
25563 \ \ if write : %xxxxWWWW --
25564 \ \ if read : -- %0000RRRR
25565 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25566 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25567 0= IF \ write LCD bits pattern
25568 AND.B #LCD_DB,TOS \
25569 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25570 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25573 THEN \ read LCD bits pattern
25576 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25577 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25578 AND.B #LCD_DB,TOS \
25583 CODE LCD_W \ byte -- write byte to LCD
25585 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
25586 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
25587 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25588 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25589 COLON \ high level word starts here
25590 TOP_LCD 2 20_US \ write high nibble first
25595 CODE LCD_WrC \ char -- Write Char
25596 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25601 CODE LCD_WrF \ func -- Write Fonction
25602 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25608 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
25613 $02 LCD_WrF 100 20_us
25617 \ : LCD_Entry_set $04 OR LCD_WrF ;
25619 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
25621 \ : LCD_Display_Shift $10 OR LCD_WrF ;
25623 \ : LCD_Fn_Set $20 OR LCD_WrF ;
25625 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
25627 \ : LCD_Goto $80 OR LCD_WrF ;
25629 \ CODE LCD_R \ -- byte read byte from LCD
25630 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25631 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25632 \ COLON \ starts a FORTH word
25633 \ TOP_LCD 2 20_us \ -- %0000HHHH
25634 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
25635 \ HI2LO \ switch from FORTH to assembler
25636 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
25637 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
25638 \ MOV @RSP+,IP \ restore IP saved by COLON
25643 \ CODE LCD_RdS \ -- status Read Status
25644 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25649 \ CODE LCD_RdC \ -- char Read Char
25650 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25655 \ -------------+------+------+------+------++---+---+---+---+---------+
25656 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
25657 \ -------------+------+------+------+------++---+---+---+---+---------+
25658 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
25659 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
25660 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
25661 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
25662 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
25663 \ -------------+------+------+------+------++---+---+---+---+---------+
25666 \ ******************************\
25667 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25668 \ ******************************\
25669 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
25670 \ ------------------------------\
25671 \ define LPM mode for ACCEPT \
25672 \ ------------------------------\
25673 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25674 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25675 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25676 BIT.B #SW2,&SW2_IN \ test switch S2
25677 0= IF \ case of switch S2 pressed
25678 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
25680 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
25683 BIT.B #SW1,&SW1_IN \ test switch S1 input
25684 0= IF \ case of Switch S1 pressed
25685 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
25687 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
25691 RETI \ CPU is ON, GIE is OFF
25696 \ ------------------------------\
25697 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25698 \ ******************************\
25699 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25700 \ ******************************\
25701 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25702 \ \ SMclock = 8|16|24 MHz
25703 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
25704 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
25705 \ \ SR(9)=new Toggle bit memory (ADD on)
25706 \ ------------------------------\
25707 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
25708 \ ------------------------------\
25709 \ define LPM mode for ACCEPT \
25710 \ ------------------------------\
25711 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25712 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25713 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25714 \ ------------------------------\
25715 \ RC5_FirstStartBitHalfCycle: \
25716 \ ------------------------------\
25717 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
25718 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
25719 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
25720 MOV #1778,X \ RC5_Period in us
25721 MOV #14,W \ count of loop
25723 \ ------------------------------\
25724 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
25725 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
25726 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
25727 \ RC5_Compute_3/4_Period: \ |
25728 RRUM #1,X \ X=1/2 cycle |
25732 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
25733 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
25735 \ ------------------------------\
25736 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
25737 \ ------------------------------\
25738 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25739 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
25740 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25741 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25742 SUB #1,W \ decrement count loop
25743 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
25744 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25745 0<> WHILE \ ----> out of loop ----+
25746 \ RC5_compute_7/4_Time_out: \ |
25747 ADD X,Y \ | out of bound = 7/4 period
25748 \ RC5_WaitHalfCycleP1.2_IFG: \ |
25750 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
25751 0>= IF \ | if cycle time out of bound
25752 BIC #$30,&TA0CTL \ | stop timer_A0
25753 RETI \ | then quit to do nothing
25755 \ ------------------------------\ |
25756 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
25758 MOV &TA0R,X \ | | get new RC5_period value
25759 REPEAT \ ----> loop back --+ |
25760 \ ------------------------------\ |
25761 \ RC5_SampleEndOf: \ <---------------------+
25762 \ ------------------------------\
25763 BIC #$30,&TA0CTL \ stop timer_A0
25764 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
25765 \ ******************************\
25766 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25767 \ ******************************\
25768 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
25769 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
25770 XOR IP,X \ (new XOR old) Toggle bit (13)
25771 BIT #BIT13,X \ X(13) = New_RC5_command
25772 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
25774 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
25775 \ ******************************\
25776 \ RC5_ComputeNewRC5word \
25777 \ ******************************\
25779 MOV &BASE,2(PSP) \ save variable BASE before use
25780 MOV TOS,0(PSP) \ save TOS before use
25781 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
25782 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
25783 \ ******************************\
25784 \ RC5_ComputeC6bit \
25785 \ ******************************\
25786 BIT #$4000,IP \ test /C6 bit in IP
25787 0= IF BIS #$40,TOS \ set C6 bit in S
25788 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
25789 \ ******************************\
25790 \ RC5_CommandByteIsDone \ RC5_code --
25791 \ ******************************\
25793 \ ------------------------------\
25794 \ Display IR_RC5 code \
25795 \ ------------------------------\
25796 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
25797 \ ------------------------------\
25798 LO2HI \ switch from assembler to FORTH
25799 ['] LCD_CLEAR IS CR \ redirects CR
25800 ['] LCD_WrC IS EMIT \ redirects EMIT
25801 $10 BASE ! \ change BASE to hexadecimal
25802 CR ." $" 2 U.R \ print IR_RC5 code
25803 ['] (CR) IS CR \ restore CR
25804 ['] (EMIT) IS EMIT \ restore EMIT
25805 HI2LO \ switch from FORTH to assembler
25806 \ ------------------------------\
25807 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
25808 \ ------------------------------\
25809 MOV @PSP+,&BASE \ restore variable BASE
25810 RETI \ CPU is ON, GIE is OFF
25815 \ ------------------------------\
25816 \ TB0CTL = %0000 0010 1001 0100\$3C0
25817 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25818 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25819 \ -- \ID input divider \ 10 = /4
25820 \ -- \MC Mode Control \ 01 = up to TB0CCR0
25821 \ - \TBCLR TimerB Clear
25824 \ --------------------------------\\
25825 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25826 \ -- \CM Capture Mode
25831 \ --- \OUTMOD \ 011 = set/reset
25837 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
25839 \ ------------------------------\
25840 \ set TimerB to make 50kHz PWM \
25841 \ ------------------------------\
25842 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25843 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
25844 \ ------------------------------\
25845 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
25846 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
25847 \ ------------------------------\
25848 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25849 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
25850 \ ------------------------------\
25851 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25852 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
25853 \ ------------------------------\
25854 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
25855 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
25856 \ ------------------------------\
25857 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
25858 \ ------------------------------\
25859 \ set TimerB to generate PWM for LCD_Vo
25860 \ ------------------------------\
25861 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
25862 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
25863 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25864 \ ------------------------------\
25865 BIS.B #LCDVo,&LCDVo_DIR \
25866 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
25867 \ ------------------------------\
25868 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25869 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25870 \ ------------------------------\
25871 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25872 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25873 \ ------------------------------\
25874 \ WDT interval init part \
25875 \ ------------------------------\
25876 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
25877 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
25878 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
25879 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
25880 \ ------------------------------\
25882 \ ------------------------------\
25883 BIS.B #RC5,&IR_IE \ enable RC5_Int
25884 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25885 \ ------------------------------\
25886 \ init interrupt vectors
25887 \ ------------------------------\
25888 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
25889 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25890 \ ------------------------------\
25891 \ define LPM mode for ACCEPT \
25892 \ ------------------------------\
25893 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25894 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25895 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25897 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
25899 \ ------------------------------\
25901 \ ------------------------------\
25902 $03E8 20_US \ 1- wait 20 ms
25903 $03 TOP_LCD \ 2- send DB5=DB4=1
25904 $CD 20_US \ 3- wait 4,1 ms
25905 $03 TOP_LCD \ 4- send again DB5=DB4=1
25906 $5 20_US \ 5- wait 0,1 ms
25907 $03 TOP_LCD \ 6- send again again DB5=DB4=1
25908 $2 20_US \ wait 40 us = LCD cycle
25909 $02 TOP_LCD \ 7- send DB5=1 DB4=0
25910 $2 20_US \ wait 40 us = LCD cycle
25911 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25912 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25913 LCD_Clear \ 10- "LCD_Clear"
25914 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25915 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25916 LCD_Clear \ 10- "LCD_Clear"
25917 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25918 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25920 ['] (CR) IS CR \ ' (CR) is CR
25921 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
25923 ." RC5toLCD is running. Type STOP to quit"
25924 \ NOECHO \ uncomment to run this app without terminal connexion
25925 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
25926 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
25930 : STOP \ stops multitasking, must to be used before downloading app
25931 ['] (WARM) IS WARM \ remove START app from FORTH init process
25932 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
25940 CODE MAX \ n1 n2 -- n3 signed maximum
25941 CMP @PSP,TOS \ n2-n1
25942 S< ?GOTO FW1 \ n2<n1
25948 CODE MIN \ n1 n2 -- n3 signed minimum
25949 CMP @PSP,TOS \ n2-n1
25950 S< ?GOTO BW1 \ n2<n1
25956 : U.R \ u n -- display u unsigned in n width (n >= 2)
25958 R> OVER - 0 MAX SPACES TYPE
25962 CODE 20_US \ n -- n * 20 us
25963 BEGIN \ 3 cycles loop + 6~
25964 \ MOV #5,W \ 3 MCLK = 1 MHz
25965 \ MOV #23,W \ 3 MCLK = 4 MHz
25966 MOV #51,W \ 3 MCLK = 8 MHz
25967 \ MOV #104,W \ 3 MCLK = 16 MHz
25968 \ MOV #158,W \ 3 MCLK = 24 MHz
25969 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
25979 CODE TOP_LCD \ LCD Sample
25980 \ \ if write : %xxxxWWWW --
25981 \ \ if read : -- %0000RRRR
25982 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25983 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25984 0= IF \ write LCD bits pattern
25985 AND.B #LCD_DB,TOS \
25986 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25987 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25990 THEN \ read LCD bits pattern
25993 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25994 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25995 AND.B #LCD_DB,TOS \
26000 CODE LCD_W \ byte -- write byte to LCD
26002 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26003 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26004 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26005 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26006 COLON \ high level word starts here
26007 TOP_LCD 2 20_US \ write high nibble first
26012 CODE LCD_WrC \ char -- Write Char
26013 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26018 CODE LCD_WrF \ func -- Write Fonction
26019 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26025 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
26030 $02 LCD_WrF 100 20_us
26034 \ : LCD_Entry_set $04 OR LCD_WrF ;
26036 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
26038 \ : LCD_Display_Shift $10 OR LCD_WrF ;
26040 \ : LCD_Fn_Set $20 OR LCD_WrF ;
26042 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
26044 \ : LCD_Goto $80 OR LCD_WrF ;
26046 \ CODE LCD_R \ -- byte read byte from LCD
26047 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26048 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26049 \ COLON \ starts a FORTH word
26050 \ TOP_LCD 2 20_us \ -- %0000HHHH
26051 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26052 \ HI2LO \ switch from FORTH to assembler
26053 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26054 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26055 \ MOV @RSP+,IP \ restore IP saved by COLON
26060 \ CODE LCD_RdS \ -- status Read Status
26061 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26066 \ CODE LCD_RdC \ -- char Read Char
26067 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26072 \ -------------+------+------+------+------++---+---+---+---+---------+
26073 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
26074 \ -------------+------+------+------+------++---+---+---+---+---------+
26075 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
26076 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
26077 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
26078 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
26079 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
26080 \ -------------+------+------+------+------++---+---+---+---+---------+
26083 \ ******************************\
26084 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26085 \ ******************************\
26086 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
26087 \ ------------------------------\
26088 \ define LPM mode for ACCEPT \
26089 \ ------------------------------\
26090 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26091 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26092 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26093 BIT.B #SW2,&SW2_IN \ test switch S2
26094 0= IF \ case of switch S2 pressed
26095 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
26097 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
26100 BIT.B #SW1,&SW1_IN \ test switch S1 input
26101 0= IF \ case of Switch S1 pressed
26102 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
26104 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
26108 RETI \ CPU is ON, GIE is OFF
26113 \ ------------------------------\
26114 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26115 \ ******************************\
26116 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26117 \ ******************************\
26118 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26119 \ \ SMclock = 8|16|24 MHz
26120 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
26121 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
26122 \ \ SR(9)=new Toggle bit memory (ADD on)
26123 \ ------------------------------\
26124 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
26125 \ ------------------------------\
26126 \ define LPM mode for ACCEPT \
26127 \ ------------------------------\
26128 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26129 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26130 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26131 \ ------------------------------\
26132 \ RC5_FirstStartBitHalfCycle: \
26133 \ ------------------------------\
26134 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
26135 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
26136 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
26137 MOV #1778,X \ RC5_Period in us
26138 MOV #14,W \ count of loop
26140 \ ------------------------------\
26141 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
26142 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
26143 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
26144 \ RC5_Compute_3/4_Period: \ |
26145 RRUM #1,X \ X=1/2 cycle |
26149 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
26150 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
26152 \ ------------------------------\
26153 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
26154 \ ------------------------------\
26155 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26156 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
26157 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26158 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26159 SUB #1,W \ decrement count loop
26160 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
26161 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26162 0<> WHILE \ ----> out of loop ----+
26163 \ RC5_compute_7/4_Time_out: \ |
26164 ADD X,Y \ | out of bound = 7/4 period
26165 \ RC5_WaitHalfCycleP1.2_IFG: \ |
26167 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
26168 0>= IF \ | if cycle time out of bound
26169 BIC #$30,&TA0CTL \ | stop timer_A0
26170 RETI \ | then quit to do nothing
26172 \ ------------------------------\ |
26173 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
26175 MOV &TA0R,X \ | | get new RC5_period value
26176 REPEAT \ ----> loop back --+ |
26177 \ ------------------------------\ |
26178 \ RC5_SampleEndOf: \ <---------------------+
26179 \ ------------------------------\
26180 BIC #$30,&TA0CTL \ stop timer_A0
26181 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
26182 \ ******************************\
26183 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26184 \ ******************************\
26185 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
26186 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
26187 XOR IP,X \ (new XOR old) Toggle bit (13)
26188 BIT #BIT13,X \ X(13) = New_RC5_command
26189 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
26191 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
26192 \ ******************************\
26193 \ RC5_ComputeNewRC5word \
26194 \ ******************************\
26196 MOV &BASE,2(PSP) \ save variable BASE before use
26197 MOV TOS,0(PSP) \ save TOS before use
26198 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
26199 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
26200 \ ******************************\
26201 \ RC5_ComputeC6bit \
26202 \ ******************************\
26203 BIT #$4000,IP \ test /C6 bit in IP
26204 0= IF BIS #$40,TOS \ set C6 bit in S
26205 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
26206 \ ******************************\
26207 \ RC5_CommandByteIsDone \ RC5_code --
26208 \ ******************************\
26210 \ ------------------------------\
26211 \ Display IR_RC5 code \
26212 \ ------------------------------\
26213 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
26214 \ ------------------------------\
26215 LO2HI \ switch from assembler to FORTH
26216 ['] LCD_CLEAR IS CR \ redirects CR
26217 ['] LCD_WrC IS EMIT \ redirects EMIT
26218 $10 BASE ! \ change BASE to hexadecimal
26219 CR ." $" 2 U.R \ print IR_RC5 code
26220 ['] (CR) IS CR \ restore CR
26221 ['] (EMIT) IS EMIT \ restore EMIT
26222 HI2LO \ switch from FORTH to assembler
26223 \ ------------------------------\
26224 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
26225 \ ------------------------------\
26226 MOV @PSP+,&BASE \ restore variable BASE
26227 RETI \ CPU is ON, GIE is OFF
26232 \ ------------------------------\
26233 \ TB0CTL = %0000 0010 1001 0100\$3C0
26234 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26235 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26236 \ -- \ID input divider \ 10 = /4
26237 \ -- \MC Mode Control \ 01 = up to TB0CCR0
26238 \ - \TBCLR TimerB Clear
26241 \ --------------------------------\\
26242 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26243 \ -- \CM Capture Mode
26248 \ --- \OUTMOD \ 011 = set/reset
26254 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
26256 \ ------------------------------\
26257 \ set TimerB to make 50kHz PWM \
26258 \ ------------------------------\
26259 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26260 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
26261 \ ------------------------------\
26262 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26263 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
26264 \ ------------------------------\
26265 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26266 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
26267 \ ------------------------------\
26268 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26269 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
26270 \ ------------------------------\
26271 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26272 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
26273 \ ------------------------------\
26274 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
26275 \ ------------------------------\
26276 \ set TimerB to generate PWM for LCD_Vo
26277 \ ------------------------------\
26278 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
26279 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
26280 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26281 \ ------------------------------\
26282 BIS.B #LCDVo,&LCDVo_DIR \
26283 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
26284 \ ------------------------------\
26285 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26286 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26287 \ ------------------------------\
26288 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26289 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26290 \ ------------------------------\
26291 \ WDT interval init part \
26292 \ ------------------------------\
26293 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
26294 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
26295 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
26296 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
26297 \ ------------------------------\
26299 \ ------------------------------\
26300 BIS.B #RC5,&IR_IE \ enable RC5_Int
26301 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26302 \ ------------------------------\
26303 \ init interrupt vectors
26304 \ ------------------------------\
26305 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
26306 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26307 \ ------------------------------\
26308 \ define LPM mode for ACCEPT \
26309 \ ------------------------------\
26310 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26311 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26312 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26314 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
26316 \ ------------------------------\
26318 \ ------------------------------\
26319 $03E8 20_US \ 1- wait 20 ms
26320 $03 TOP_LCD \ 2- send DB5=DB4=1
26321 $CD 20_US \ 3- wait 4,1 ms
26322 $03 TOP_LCD \ 4- send again DB5=DB4=1
26323 $5 20_US \ 5- wait 0,1 ms
26324 $03 TOP_LCD \ 6- send again again DB5=DB4=1
26325 $2 20_US \ wait 40 us = LCD cycle
26326 $02 TOP_LCD \ 7- send DB5=1 DB4=0
26327 $2 20_US \ wait 40 us = LCD cycle
26328 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26329 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26330 LCD_Clear \ 10- "LCD_Clear"
26331 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26332 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26333 LCD_Clear \ 10- "LCD_Clear"
26334 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26335 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26337 ['] (CR) IS CR \ ' (CR) is CR
26338 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
26340 ." RC5toLCD is running. Type STOP to quit"
26341 \ NOECHO \ uncomment to run this app without terminal connexion
26342 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
26343 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
26347 : STOP \ stops multitasking, must to be used before downloading app
26348 ['] (WARM) IS WARM \ remove START app from FORTH init process
26349 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
26357 CODE MAX \ n1 n2 -- n3 signed maximum
26358 CMP @PSP,TOS \ n2-n1
26359 S< ?GOTO FW1 \ n2<n1
26365 CODE MIN \ n1 n2 -- n3 signed minimum
26366 CMP @PSP,TOS \ n2-n1
26367 S< ?GOTO BW1 \ n2<n1
26373 : U.R \ u n -- display u unsigned in n width (n >= 2)
26375 R> OVER - 0 MAX SPACES TYPE
26379 CODE 20_US \ n -- n * 20 us
26380 BEGIN \ 3 cycles loop + 6~
26381 \ MOV #5,W \ 3 MCLK = 1 MHz
26382 \ MOV #23,W \ 3 MCLK = 4 MHz
26383 MOV #51,W \ 3 MCLK = 8 MHz
26384 \ MOV #104,W \ 3 MCLK = 16 MHz
26385 \ MOV #158,W \ 3 MCLK = 24 MHz
26386 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
26396 CODE TOP_LCD \ LCD Sample
26397 \ \ if write : %xxxxWWWW --
26398 \ \ if read : -- %0000RRRR
26399 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26400 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26401 0= IF \ write LCD bits pattern
26402 AND.B #LCD_DB,TOS \
26403 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26404 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26407 THEN \ read LCD bits pattern
26410 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26411 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26412 AND.B #LCD_DB,TOS \
26417 CODE LCD_W \ byte -- write byte to LCD
26419 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26420 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26421 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26422 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26423 COLON \ high level word starts here
26424 TOP_LCD 2 20_US \ write high nibble first
26429 CODE LCD_WrC \ char -- Write Char
26430 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26435 CODE LCD_WrF \ func -- Write Fonction
26436 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26442 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
26447 $02 LCD_WrF 100 20_us
26451 \ : LCD_Entry_set $04 OR LCD_WrF ;
26453 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
26455 \ : LCD_Display_Shift $10 OR LCD_WrF ;
26457 \ : LCD_Fn_Set $20 OR LCD_WrF ;
26459 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
26461 \ : LCD_Goto $80 OR LCD_WrF ;
26463 \ CODE LCD_R \ -- byte read byte from LCD
26464 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26465 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26466 \ COLON \ starts a FORTH word
26467 \ TOP_LCD 2 20_us \ -- %0000HHHH
26468 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26469 \ HI2LO \ switch from FORTH to assembler
26470 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26471 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26472 \ MOV @RSP+,IP \ restore IP saved by COLON
26477 \ CODE LCD_RdS \ -- status Read Status
26478 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26483 \ CODE LCD_RdC \ -- char Read Char
26484 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26489 \ -------------+------+------+------+------++---+---+---+---+---------+
26490 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
26491 \ -------------+------+------+------+------++---+---+---+---+---------+
26492 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
26493 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
26494 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
26495 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
26496 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
26497 \ -------------+------+------+------+------++---+---+---+---+---------+
26500 \ ******************************\
26501 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26502 \ ******************************\
26503 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
26504 \ ------------------------------\
26505 \ define LPM mode for ACCEPT \
26506 \ ------------------------------\
26507 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26508 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26509 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26510 BIT.B #SW2,&SW2_IN \ test switch S2
26511 0= IF \ case of switch S2 pressed
26512 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
26514 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
26517 BIT.B #SW1,&SW1_IN \ test switch S1 input
26518 0= IF \ case of Switch S1 pressed
26519 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
26521 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
26525 RETI \ CPU is ON, GIE is OFF
26530 \ ------------------------------\
26531 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26532 \ ******************************\
26533 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26534 \ ******************************\
26535 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26536 \ \ SMclock = 8|16|24 MHz
26537 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
26538 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
26539 \ \ SR(9)=new Toggle bit memory (ADD on)
26540 \ ------------------------------\
26541 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
26542 \ ------------------------------\
26543 \ define LPM mode for ACCEPT \
26544 \ ------------------------------\
26545 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26546 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26547 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26548 \ ------------------------------\
26549 \ RC5_FirstStartBitHalfCycle: \
26550 \ ------------------------------\
26551 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
26552 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
26553 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
26554 MOV #1778,X \ RC5_Period in us
26555 MOV #14,W \ count of loop
26557 \ ------------------------------\
26558 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
26559 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
26560 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
26561 \ RC5_Compute_3/4_Period: \ |
26562 RRUM #1,X \ X=1/2 cycle |
26566 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
26567 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
26569 \ ------------------------------\
26570 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
26571 \ ------------------------------\
26572 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26573 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
26574 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26575 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26576 SUB #1,W \ decrement count loop
26577 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
26578 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26579 0<> WHILE \ ----> out of loop ----+
26580 \ RC5_compute_7/4_Time_out: \ |
26581 ADD X,Y \ | out of bound = 7/4 period
26582 \ RC5_WaitHalfCycleP1.2_IFG: \ |
26584 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
26585 0>= IF \ | if cycle time out of bound
26586 BIC #$30,&TA0CTL \ | stop timer_A0
26587 RETI \ | then quit to do nothing
26589 \ ------------------------------\ |
26590 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
26592 MOV &TA0R,X \ | | get new RC5_period value
26593 REPEAT \ ----> loop back --+ |
26594 \ ------------------------------\ |
26595 \ RC5_SampleEndOf: \ <---------------------+
26596 \ ------------------------------\
26597 BIC #$30,&TA0CTL \ stop timer_A0
26598 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
26599 \ ******************************\
26600 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26601 \ ******************************\
26602 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
26603 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
26604 XOR IP,X \ (new XOR old) Toggle bit (13)
26605 BIT #BIT13,X \ X(13) = New_RC5_command
26606 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
26608 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
26609 \ ******************************\
26610 \ RC5_ComputeNewRC5word \
26611 \ ******************************\
26613 MOV &BASE,2(PSP) \ save variable BASE before use
26614 MOV TOS,0(PSP) \ save TOS before use
26615 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
26616 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
26617 \ ******************************\
26618 \ RC5_ComputeC6bit \
26619 \ ******************************\
26620 BIT #$4000,IP \ test /C6 bit in IP
26621 0= IF BIS #$40,TOS \ set C6 bit in S
26622 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
26623 \ ******************************\
26624 \ RC5_CommandByteIsDone \ RC5_code --
26625 \ ******************************\
26627 \ ------------------------------\
26628 \ Display IR_RC5 code \
26629 \ ------------------------------\
26630 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
26631 \ ------------------------------\
26632 LO2HI \ switch from assembler to FORTH
26633 ['] LCD_CLEAR IS CR \ redirects CR
26634 ['] LCD_WrC IS EMIT \ redirects EMIT
26635 $10 BASE ! \ change BASE to hexadecimal
26636 CR ." $" 2 U.R \ print IR_RC5 code
26637 ['] (CR) IS CR \ restore CR
26638 ['] (EMIT) IS EMIT \ restore EMIT
26639 HI2LO \ switch from FORTH to assembler
26640 \ ------------------------------\
26641 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
26642 \ ------------------------------\
26643 MOV @PSP+,&BASE \ restore variable BASE
26644 RETI \ CPU is ON, GIE is OFF
26649 \ ------------------------------\
26650 \ TB0CTL = %0000 0010 1001 0100\$3C0
26651 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26652 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26653 \ -- \ID input divider \ 10 = /4
26654 \ -- \MC Mode Control \ 01 = up to TB0CCR0
26655 \ - \TBCLR TimerB Clear
26658 \ --------------------------------\\
26659 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26660 \ -- \CM Capture Mode
26665 \ --- \OUTMOD \ 011 = set/reset
26671 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
26673 \ ------------------------------\
26674 \ set TimerB to make 50kHz PWM \
26675 \ ------------------------------\
26676 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26677 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
26678 \ ------------------------------\
26679 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
26680 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
26681 \ ------------------------------\
26682 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26683 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
26684 \ ------------------------------\
26685 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26686 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
26687 \ ------------------------------\
26688 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
26689 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
26690 \ ------------------------------\
26691 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
26692 \ ------------------------------\
26693 \ set TimerB to generate PWM for LCD_Vo
26694 \ ------------------------------\
26695 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
26696 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
26697 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26698 \ ------------------------------\
26699 BIS.B #LCDVo,&LCDVo_DIR \
26700 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
26701 \ ------------------------------\
26702 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26703 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26704 \ ------------------------------\
26705 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26706 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26707 \ ------------------------------\
26708 \ WDT interval init part \
26709 \ ------------------------------\
26710 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
26711 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
26712 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
26713 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
26714 \ ------------------------------\
26716 \ ------------------------------\
26717 BIS.B #RC5,&IR_IE \ enable RC5_Int
26718 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26719 \ ------------------------------\
26720 \ init interrupt vectors
26721 \ ------------------------------\
26722 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
26723 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26724 \ ------------------------------\
26725 \ define LPM mode for ACCEPT \
26726 \ ------------------------------\
26727 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26728 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26729 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26731 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
26733 \ ------------------------------\
26735 \ ------------------------------\
26736 $03E8 20_US \ 1- wait 20 ms
26737 $03 TOP_LCD \ 2- send DB5=DB4=1
26738 $CD 20_US \ 3- wait 4,1 ms
26739 $03 TOP_LCD \ 4- send again DB5=DB4=1
26740 $5 20_US \ 5- wait 0,1 ms
26741 $03 TOP_LCD \ 6- send again again DB5=DB4=1
26742 $2 20_US \ wait 40 us = LCD cycle
26743 $02 TOP_LCD \ 7- send DB5=1 DB4=0
26744 $2 20_US \ wait 40 us = LCD cycle
26745 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26746 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26747 LCD_Clear \ 10- "LCD_Clear"
26748 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26749 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26750 LCD_Clear \ 10- "LCD_Clear"
26751 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26752 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26754 ['] (CR) IS CR \ ' (CR) is CR
26755 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
26757 ." RC5toLCD is running. Type STOP to quit"
26758 \ NOECHO \ uncomment to run this app without terminal connexion
26759 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
26760 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
26764 : STOP \ stops multitasking, must to be used before downloading app
26765 ['] (WARM) IS WARM \ remove START app from FORTH init process
26766 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
26774 CODE MAX \ n1 n2 -- n3 signed maximum
26775 CMP @PSP,TOS \ n2-n1
26776 S< ?GOTO FW1 \ n2<n1
26782 CODE MIN \ n1 n2 -- n3 signed minimum
26783 CMP @PSP,TOS \ n2-n1
26784 S< ?GOTO BW1 \ n2<n1
26790 : U.R \ u n -- display u unsigned in n width (n >= 2)
26792 R> OVER - 0 MAX SPACES TYPE
26796 CODE 20_US \ n -- n * 20 us
26797 BEGIN \ 3 cycles loop + 6~
26798 \ MOV #5,W \ 3 MCLK = 1 MHz
26799 \ MOV #23,W \ 3 MCLK = 4 MHz
26800 MOV #51,W \ 3 MCLK = 8 MHz
26801 \ MOV #104,W \ 3 MCLK = 16 MHz
26802 \ MOV #158,W \ 3 MCLK = 24 MHz
26803 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
26813 CODE TOP_LCD \ LCD Sample
26814 \ \ if write : %xxxxWWWW --
26815 \ \ if read : -- %0000RRRR
26816 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26817 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26818 0= IF \ write LCD bits pattern
26819 AND.B #LCD_DB,TOS \
26820 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26821 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26824 THEN \ read LCD bits pattern
26827 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26828 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26829 AND.B #LCD_DB,TOS \
26834 CODE LCD_W \ byte -- write byte to LCD
26836 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
26837 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
26838 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26839 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26840 COLON \ high level word starts here
26841 TOP_LCD 2 20_US \ write high nibble first
26846 CODE LCD_WrC \ char -- Write Char
26847 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26852 CODE LCD_WrF \ func -- Write Fonction
26853 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26859 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
26864 $02 LCD_WrF 100 20_us
26868 \ : LCD_Entry_set $04 OR LCD_WrF ;
26870 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
26872 \ : LCD_Display_Shift $10 OR LCD_WrF ;
26874 \ : LCD_Fn_Set $20 OR LCD_WrF ;
26876 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
26878 \ : LCD_Goto $80 OR LCD_WrF ;
26880 \ CODE LCD_R \ -- byte read byte from LCD
26881 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26882 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26883 \ COLON \ starts a FORTH word
26884 \ TOP_LCD 2 20_us \ -- %0000HHHH
26885 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
26886 \ HI2LO \ switch from FORTH to assembler
26887 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
26888 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
26889 \ MOV @RSP+,IP \ restore IP saved by COLON
26894 \ CODE LCD_RdS \ -- status Read Status
26895 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26900 \ CODE LCD_RdC \ -- char Read Char
26901 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26906 \ -------------+------+------+------+------++---+---+---+---+---------+
26907 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
26908 \ -------------+------+------+------+------++---+---+---+---+---------+
26909 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
26910 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
26911 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
26912 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
26913 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
26914 \ -------------+------+------+------+------++---+---+---+---+---------+
26917 \ ******************************\
26918 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26919 \ ******************************\
26920 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
26921 \ ------------------------------\
26922 \ define LPM mode for ACCEPT \
26923 \ ------------------------------\
26924 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26925 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26926 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26927 BIT.B #SW2,&SW2_IN \ test switch S2
26928 0= IF \ case of switch S2 pressed
26929 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
26931 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
26934 BIT.B #SW1,&SW1_IN \ test switch S1 input
26935 0= IF \ case of Switch S1 pressed
26936 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
26938 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
26942 RETI \ CPU is ON, GIE is OFF
26947 \ ------------------------------\
26948 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26949 \ ******************************\
26950 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26951 \ ******************************\
26952 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26953 \ \ SMclock = 8|16|24 MHz
26954 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
26955 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
26956 \ \ SR(9)=new Toggle bit memory (ADD on)
26957 \ ------------------------------\
26958 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
26959 \ ------------------------------\
26960 \ define LPM mode for ACCEPT \
26961 \ ------------------------------\
26962 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26963 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26964 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26965 \ ------------------------------\
26966 \ RC5_FirstStartBitHalfCycle: \
26967 \ ------------------------------\
26968 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
26969 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
26970 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
26971 MOV #1778,X \ RC5_Period in us
26972 MOV #14,W \ count of loop
26974 \ ------------------------------\
26975 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
26976 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
26977 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
26978 \ RC5_Compute_3/4_Period: \ |
26979 RRUM #1,X \ X=1/2 cycle |
26983 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
26984 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
26986 \ ------------------------------\
26987 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
26988 \ ------------------------------\
26989 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26990 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
26991 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26992 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26993 SUB #1,W \ decrement count loop
26994 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
26995 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26996 0<> WHILE \ ----> out of loop ----+
26997 \ RC5_compute_7/4_Time_out: \ |
26998 ADD X,Y \ | out of bound = 7/4 period
26999 \ RC5_WaitHalfCycleP1.2_IFG: \ |
27001 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
27002 0>= IF \ | if cycle time out of bound
27003 BIC #$30,&TA0CTL \ | stop timer_A0
27004 RETI \ | then quit to do nothing
27006 \ ------------------------------\ |
27007 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
27009 MOV &TA0R,X \ | | get new RC5_period value
27010 REPEAT \ ----> loop back --+ |
27011 \ ------------------------------\ |
27012 \ RC5_SampleEndOf: \ <---------------------+
27013 \ ------------------------------\
27014 BIC #$30,&TA0CTL \ stop timer_A0
27015 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
27016 \ ******************************\
27017 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27018 \ ******************************\
27019 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
27020 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
27021 XOR IP,X \ (new XOR old) Toggle bit (13)
27022 BIT #BIT13,X \ X(13) = New_RC5_command
27023 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
27025 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
27026 \ ******************************\
27027 \ RC5_ComputeNewRC5word \
27028 \ ******************************\
27030 MOV &BASE,2(PSP) \ save variable BASE before use
27031 MOV TOS,0(PSP) \ save TOS before use
27032 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
27033 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
27034 \ ******************************\
27035 \ RC5_ComputeC6bit \
27036 \ ******************************\
27037 BIT #$4000,IP \ test /C6 bit in IP
27038 0= IF BIS #$40,TOS \ set C6 bit in S
27039 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
27040 \ ******************************\
27041 \ RC5_CommandByteIsDone \ RC5_code --
27042 \ ******************************\
27044 \ ------------------------------\
27045 \ Display IR_RC5 code \
27046 \ ------------------------------\
27047 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
27048 \ ------------------------------\
27049 LO2HI \ switch from assembler to FORTH
27050 ['] LCD_CLEAR IS CR \ redirects CR
27051 ['] LCD_WrC IS EMIT \ redirects EMIT
27052 $10 BASE ! \ change BASE to hexadecimal
27053 CR ." $" 2 U.R \ print IR_RC5 code
27054 ['] (CR) IS CR \ restore CR
27055 ['] (EMIT) IS EMIT \ restore EMIT
27056 HI2LO \ switch from FORTH to assembler
27057 \ ------------------------------\
27058 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
27059 \ ------------------------------\
27060 MOV @PSP+,&BASE \ restore variable BASE
27061 RETI \ CPU is ON, GIE is OFF
27066 \ ------------------------------\
27067 \ TB0CTL = %0000 0010 1001 0100\$3C0
27068 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27069 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27070 \ -- \ID input divider \ 10 = /4
27071 \ -- \MC Mode Control \ 01 = up to TB0CCR0
27072 \ - \TBCLR TimerB Clear
27075 \ --------------------------------\\
27076 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27077 \ -- \CM Capture Mode
27082 \ --- \OUTMOD \ 011 = set/reset
27088 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
27090 \ ------------------------------\
27091 \ set TimerB to make 50kHz PWM \
27092 \ ------------------------------\
27093 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27094 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
27095 \ ------------------------------\
27096 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27097 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
27098 \ ------------------------------\
27099 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27100 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
27101 \ ------------------------------\
27102 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27103 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
27104 \ ------------------------------\
27105 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27106 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
27107 \ ------------------------------\
27108 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
27109 \ ------------------------------\
27110 \ set TimerB to generate PWM for LCD_Vo
27111 \ ------------------------------\
27112 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
27113 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
27114 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27115 \ ------------------------------\
27116 BIS.B #LCDVo,&LCDVo_DIR \
27117 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
27118 \ ------------------------------\
27119 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27120 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27121 \ ------------------------------\
27122 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27123 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27124 \ ------------------------------\
27125 \ WDT interval init part \
27126 \ ------------------------------\
27127 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
27128 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
27129 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
27130 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
27131 \ ------------------------------\
27133 \ ------------------------------\
27134 BIS.B #RC5,&IR_IE \ enable RC5_Int
27135 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27136 \ ------------------------------\
27137 \ init interrupt vectors
27138 \ ------------------------------\
27139 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
27140 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27141 \ ------------------------------\
27142 \ define LPM mode for ACCEPT \
27143 \ ------------------------------\
27144 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27145 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27146 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27148 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
27150 \ ------------------------------\
27152 \ ------------------------------\
27153 $03E8 20_US \ 1- wait 20 ms
27154 $03 TOP_LCD \ 2- send DB5=DB4=1
27155 $CD 20_US \ 3- wait 4,1 ms
27156 $03 TOP_LCD \ 4- send again DB5=DB4=1
27157 $5 20_US \ 5- wait 0,1 ms
27158 $03 TOP_LCD \ 6- send again again DB5=DB4=1
27159 $2 20_US \ wait 40 us = LCD cycle
27160 $02 TOP_LCD \ 7- send DB5=1 DB4=0
27161 $2 20_US \ wait 40 us = LCD cycle
27162 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27163 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27164 LCD_Clear \ 10- "LCD_Clear"
27165 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27166 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27167 LCD_Clear \ 10- "LCD_Clear"
27168 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27169 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27171 ['] (CR) IS CR \ ' (CR) is CR
27172 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
27174 ." RC5toLCD is running. Type STOP to quit"
27175 \ NOECHO \ uncomment to run this app without terminal connexion
27176 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
27177 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
27181 : STOP \ stops multitasking, must to be used before downloading app
27182 ['] (WARM) IS WARM \ remove START app from FORTH init process
27183 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
27191 CODE MAX \ n1 n2 -- n3 signed maximum
27192 CMP @PSP,TOS \ n2-n1
27193 S< ?GOTO FW1 \ n2<n1
27199 CODE MIN \ n1 n2 -- n3 signed minimum
27200 CMP @PSP,TOS \ n2-n1
27201 S< ?GOTO BW1 \ n2<n1
27207 : U.R \ u n -- display u unsigned in n width (n >= 2)
27209 R> OVER - 0 MAX SPACES TYPE
27213 CODE 20_US \ n -- n * 20 us
27214 BEGIN \ 3 cycles loop + 6~
27215 \ MOV #5,W \ 3 MCLK = 1 MHz
27216 \ MOV #23,W \ 3 MCLK = 4 MHz
27217 MOV #51,W \ 3 MCLK = 8 MHz
27218 \ MOV #104,W \ 3 MCLK = 16 MHz
27219 \ MOV #158,W \ 3 MCLK = 24 MHz
27220 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
27230 CODE TOP_LCD \ LCD Sample
27231 \ \ if write : %xxxxWWWW --
27232 \ \ if read : -- %0000RRRR
27233 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27234 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27235 0= IF \ write LCD bits pattern
27236 AND.B #LCD_DB,TOS \
27237 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27238 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27241 THEN \ read LCD bits pattern
27244 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27245 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27246 AND.B #LCD_DB,TOS \
27251 CODE LCD_W \ byte -- write byte to LCD
27253 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27254 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27255 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27256 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27257 COLON \ high level word starts here
27258 TOP_LCD 2 20_US \ write high nibble first
27263 CODE LCD_WrC \ char -- Write Char
27264 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27269 CODE LCD_WrF \ func -- Write Fonction
27270 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27276 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
27281 $02 LCD_WrF 100 20_us
27285 \ : LCD_Entry_set $04 OR LCD_WrF ;
27287 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
27289 \ : LCD_Display_Shift $10 OR LCD_WrF ;
27291 \ : LCD_Fn_Set $20 OR LCD_WrF ;
27293 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
27295 \ : LCD_Goto $80 OR LCD_WrF ;
27297 \ CODE LCD_R \ -- byte read byte from LCD
27298 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27299 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27300 \ COLON \ starts a FORTH word
27301 \ TOP_LCD 2 20_us \ -- %0000HHHH
27302 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27303 \ HI2LO \ switch from FORTH to assembler
27304 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27305 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27306 \ MOV @RSP+,IP \ restore IP saved by COLON
27311 \ CODE LCD_RdS \ -- status Read Status
27312 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27317 \ CODE LCD_RdC \ -- char Read Char
27318 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27323 \ -------------+------+------+------+------++---+---+---+---+---------+
27324 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
27325 \ -------------+------+------+------+------++---+---+---+---+---------+
27326 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
27327 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
27328 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
27329 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
27330 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
27331 \ -------------+------+------+------+------++---+---+---+---+---------+
27334 \ ******************************\
27335 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27336 \ ******************************\
27337 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
27338 \ ------------------------------\
27339 \ define LPM mode for ACCEPT \
27340 \ ------------------------------\
27341 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27342 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27343 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27344 BIT.B #SW2,&SW2_IN \ test switch S2
27345 0= IF \ case of switch S2 pressed
27346 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
27348 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
27351 BIT.B #SW1,&SW1_IN \ test switch S1 input
27352 0= IF \ case of Switch S1 pressed
27353 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
27355 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
27359 RETI \ CPU is ON, GIE is OFF
27364 \ ------------------------------\
27365 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27366 \ ******************************\
27367 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27368 \ ******************************\
27369 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27370 \ \ SMclock = 8|16|24 MHz
27371 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
27372 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
27373 \ \ SR(9)=new Toggle bit memory (ADD on)
27374 \ ------------------------------\
27375 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
27376 \ ------------------------------\
27377 \ define LPM mode for ACCEPT \
27378 \ ------------------------------\
27379 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27380 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27381 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27382 \ ------------------------------\
27383 \ RC5_FirstStartBitHalfCycle: \
27384 \ ------------------------------\
27385 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
27386 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
27387 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
27388 MOV #1778,X \ RC5_Period in us
27389 MOV #14,W \ count of loop
27391 \ ------------------------------\
27392 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
27393 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
27394 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
27395 \ RC5_Compute_3/4_Period: \ |
27396 RRUM #1,X \ X=1/2 cycle |
27400 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
27401 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
27403 \ ------------------------------\
27404 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
27405 \ ------------------------------\
27406 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27407 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
27408 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27409 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27410 SUB #1,W \ decrement count loop
27411 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
27412 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27413 0<> WHILE \ ----> out of loop ----+
27414 \ RC5_compute_7/4_Time_out: \ |
27415 ADD X,Y \ | out of bound = 7/4 period
27416 \ RC5_WaitHalfCycleP1.2_IFG: \ |
27418 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
27419 0>= IF \ | if cycle time out of bound
27420 BIC #$30,&TA0CTL \ | stop timer_A0
27421 RETI \ | then quit to do nothing
27423 \ ------------------------------\ |
27424 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
27426 MOV &TA0R,X \ | | get new RC5_period value
27427 REPEAT \ ----> loop back --+ |
27428 \ ------------------------------\ |
27429 \ RC5_SampleEndOf: \ <---------------------+
27430 \ ------------------------------\
27431 BIC #$30,&TA0CTL \ stop timer_A0
27432 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
27433 \ ******************************\
27434 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27435 \ ******************************\
27436 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
27437 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
27438 XOR IP,X \ (new XOR old) Toggle bit (13)
27439 BIT #BIT13,X \ X(13) = New_RC5_command
27440 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
27442 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
27443 \ ******************************\
27444 \ RC5_ComputeNewRC5word \
27445 \ ******************************\
27447 MOV &BASE,2(PSP) \ save variable BASE before use
27448 MOV TOS,0(PSP) \ save TOS before use
27449 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
27450 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
27451 \ ******************************\
27452 \ RC5_ComputeC6bit \
27453 \ ******************************\
27454 BIT #$4000,IP \ test /C6 bit in IP
27455 0= IF BIS #$40,TOS \ set C6 bit in S
27456 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
27457 \ ******************************\
27458 \ RC5_CommandByteIsDone \ RC5_code --
27459 \ ******************************\
27461 \ ------------------------------\
27462 \ Display IR_RC5 code \
27463 \ ------------------------------\
27464 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
27465 \ ------------------------------\
27466 LO2HI \ switch from assembler to FORTH
27467 ['] LCD_CLEAR IS CR \ redirects CR
27468 ['] LCD_WrC IS EMIT \ redirects EMIT
27469 $10 BASE ! \ change BASE to hexadecimal
27470 CR ." $" 2 U.R \ print IR_RC5 code
27471 ['] (CR) IS CR \ restore CR
27472 ['] (EMIT) IS EMIT \ restore EMIT
27473 HI2LO \ switch from FORTH to assembler
27474 \ ------------------------------\
27475 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
27476 \ ------------------------------\
27477 MOV @PSP+,&BASE \ restore variable BASE
27478 RETI \ CPU is ON, GIE is OFF
27483 \ ------------------------------\
27484 \ TB0CTL = %0000 0010 1001 0100\$3C0
27485 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27486 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27487 \ -- \ID input divider \ 10 = /4
27488 \ -- \MC Mode Control \ 01 = up to TB0CCR0
27489 \ - \TBCLR TimerB Clear
27492 \ --------------------------------\\
27493 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27494 \ -- \CM Capture Mode
27499 \ --- \OUTMOD \ 011 = set/reset
27505 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
27507 \ ------------------------------\
27508 \ set TimerB to make 50kHz PWM \
27509 \ ------------------------------\
27510 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27511 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
27512 \ ------------------------------\
27513 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27514 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
27515 \ ------------------------------\
27516 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27517 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
27518 \ ------------------------------\
27519 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27520 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
27521 \ ------------------------------\
27522 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27523 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
27524 \ ------------------------------\
27525 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
27526 \ ------------------------------\
27527 \ set TimerB to generate PWM for LCD_Vo
27528 \ ------------------------------\
27529 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
27530 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
27531 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27532 \ ------------------------------\
27533 BIS.B #LCDVo,&LCDVo_DIR \
27534 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
27535 \ ------------------------------\
27536 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27537 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27538 \ ------------------------------\
27539 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27540 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27541 \ ------------------------------\
27542 \ WDT interval init part \
27543 \ ------------------------------\
27544 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
27545 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
27546 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
27547 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
27548 \ ------------------------------\
27550 \ ------------------------------\
27551 BIS.B #RC5,&IR_IE \ enable RC5_Int
27552 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27553 \ ------------------------------\
27554 \ init interrupt vectors
27555 \ ------------------------------\
27556 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
27557 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27558 \ ------------------------------\
27559 \ define LPM mode for ACCEPT \
27560 \ ------------------------------\
27561 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27562 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27563 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27565 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
27567 \ ------------------------------\
27569 \ ------------------------------\
27570 $03E8 20_US \ 1- wait 20 ms
27571 $03 TOP_LCD \ 2- send DB5=DB4=1
27572 $CD 20_US \ 3- wait 4,1 ms
27573 $03 TOP_LCD \ 4- send again DB5=DB4=1
27574 $5 20_US \ 5- wait 0,1 ms
27575 $03 TOP_LCD \ 6- send again again DB5=DB4=1
27576 $2 20_US \ wait 40 us = LCD cycle
27577 $02 TOP_LCD \ 7- send DB5=1 DB4=0
27578 $2 20_US \ wait 40 us = LCD cycle
27579 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27580 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27581 LCD_Clear \ 10- "LCD_Clear"
27582 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27583 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27584 LCD_Clear \ 10- "LCD_Clear"
27585 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27586 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27588 ['] (CR) IS CR \ ' (CR) is CR
27589 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
27591 ." RC5toLCD is running. Type STOP to quit"
27592 \ NOECHO \ uncomment to run this app without terminal connexion
27593 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
27594 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
27598 : STOP \ stops multitasking, must to be used before downloading app
27599 ['] (WARM) IS WARM \ remove START app from FORTH init process
27600 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
27608 CODE MAX \ n1 n2 -- n3 signed maximum
27609 CMP @PSP,TOS \ n2-n1
27610 S< ?GOTO FW1 \ n2<n1
27616 CODE MIN \ n1 n2 -- n3 signed minimum
27617 CMP @PSP,TOS \ n2-n1
27618 S< ?GOTO BW1 \ n2<n1
27624 : U.R \ u n -- display u unsigned in n width (n >= 2)
27626 R> OVER - 0 MAX SPACES TYPE
27630 CODE 20_US \ n -- n * 20 us
27631 BEGIN \ 3 cycles loop + 6~
27632 \ MOV #5,W \ 3 MCLK = 1 MHz
27633 \ MOV #23,W \ 3 MCLK = 4 MHz
27634 MOV #51,W \ 3 MCLK = 8 MHz
27635 \ MOV #104,W \ 3 MCLK = 16 MHz
27636 \ MOV #158,W \ 3 MCLK = 24 MHz
27637 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
27647 CODE TOP_LCD \ LCD Sample
27648 \ \ if write : %xxxxWWWW --
27649 \ \ if read : -- %0000RRRR
27650 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27651 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27652 0= IF \ write LCD bits pattern
27653 AND.B #LCD_DB,TOS \
27654 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27655 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27658 THEN \ read LCD bits pattern
27661 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27662 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27663 AND.B #LCD_DB,TOS \
27668 CODE LCD_W \ byte -- write byte to LCD
27670 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
27671 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
27672 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27673 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27674 COLON \ high level word starts here
27675 TOP_LCD 2 20_US \ write high nibble first
27680 CODE LCD_WrC \ char -- Write Char
27681 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27686 CODE LCD_WrF \ func -- Write Fonction
27687 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27693 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
27698 $02 LCD_WrF 100 20_us
27702 \ : LCD_Entry_set $04 OR LCD_WrF ;
27704 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
27706 \ : LCD_Display_Shift $10 OR LCD_WrF ;
27708 \ : LCD_Fn_Set $20 OR LCD_WrF ;
27710 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
27712 \ : LCD_Goto $80 OR LCD_WrF ;
27714 \ CODE LCD_R \ -- byte read byte from LCD
27715 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27716 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27717 \ COLON \ starts a FORTH word
27718 \ TOP_LCD 2 20_us \ -- %0000HHHH
27719 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
27720 \ HI2LO \ switch from FORTH to assembler
27721 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
27722 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
27723 \ MOV @RSP+,IP \ restore IP saved by COLON
27728 \ CODE LCD_RdS \ -- status Read Status
27729 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27734 \ CODE LCD_RdC \ -- char Read Char
27735 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27740 \ -------------+------+------+------+------++---+---+---+---+---------+
27741 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
27742 \ -------------+------+------+------+------++---+---+---+---+---------+
27743 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
27744 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
27745 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
27746 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
27747 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
27748 \ -------------+------+------+------+------++---+---+---+---+---------+
27751 \ ******************************\
27752 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27753 \ ******************************\
27754 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
27755 \ ------------------------------\
27756 \ define LPM mode for ACCEPT \
27757 \ ------------------------------\
27758 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27759 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27760 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27761 BIT.B #SW2,&SW2_IN \ test switch S2
27762 0= IF \ case of switch S2 pressed
27763 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
27765 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
27768 BIT.B #SW1,&SW1_IN \ test switch S1 input
27769 0= IF \ case of Switch S1 pressed
27770 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
27772 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
27776 RETI \ CPU is ON, GIE is OFF
27781 \ ------------------------------\
27782 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27783 \ ******************************\
27784 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27785 \ ******************************\
27786 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27787 \ \ SMclock = 8|16|24 MHz
27788 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
27789 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
27790 \ \ SR(9)=new Toggle bit memory (ADD on)
27791 \ ------------------------------\
27792 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
27793 \ ------------------------------\
27794 \ define LPM mode for ACCEPT \
27795 \ ------------------------------\
27796 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27797 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27798 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27799 \ ------------------------------\
27800 \ RC5_FirstStartBitHalfCycle: \
27801 \ ------------------------------\
27802 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
27803 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
27804 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
27805 MOV #1778,X \ RC5_Period in us
27806 MOV #14,W \ count of loop
27808 \ ------------------------------\
27809 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
27810 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
27811 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
27812 \ RC5_Compute_3/4_Period: \ |
27813 RRUM #1,X \ X=1/2 cycle |
27817 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
27818 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
27820 \ ------------------------------\
27821 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
27822 \ ------------------------------\
27823 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27824 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
27825 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27826 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27827 SUB #1,W \ decrement count loop
27828 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
27829 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27830 0<> WHILE \ ----> out of loop ----+
27831 \ RC5_compute_7/4_Time_out: \ |
27832 ADD X,Y \ | out of bound = 7/4 period
27833 \ RC5_WaitHalfCycleP1.2_IFG: \ |
27835 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
27836 0>= IF \ | if cycle time out of bound
27837 BIC #$30,&TA0CTL \ | stop timer_A0
27838 RETI \ | then quit to do nothing
27840 \ ------------------------------\ |
27841 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
27843 MOV &TA0R,X \ | | get new RC5_period value
27844 REPEAT \ ----> loop back --+ |
27845 \ ------------------------------\ |
27846 \ RC5_SampleEndOf: \ <---------------------+
27847 \ ------------------------------\
27848 BIC #$30,&TA0CTL \ stop timer_A0
27849 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
27850 \ ******************************\
27851 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27852 \ ******************************\
27853 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
27854 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
27855 XOR IP,X \ (new XOR old) Toggle bit (13)
27856 BIT #BIT13,X \ X(13) = New_RC5_command
27857 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
27859 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
27860 \ ******************************\
27861 \ RC5_ComputeNewRC5word \
27862 \ ******************************\
27864 MOV &BASE,2(PSP) \ save variable BASE before use
27865 MOV TOS,0(PSP) \ save TOS before use
27866 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
27867 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
27868 \ ******************************\
27869 \ RC5_ComputeC6bit \
27870 \ ******************************\
27871 BIT #$4000,IP \ test /C6 bit in IP
27872 0= IF BIS #$40,TOS \ set C6 bit in S
27873 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
27874 \ ******************************\
27875 \ RC5_CommandByteIsDone \ RC5_code --
27876 \ ******************************\
27878 \ ------------------------------\
27879 \ Display IR_RC5 code \
27880 \ ------------------------------\
27881 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
27882 \ ------------------------------\
27883 LO2HI \ switch from assembler to FORTH
27884 ['] LCD_CLEAR IS CR \ redirects CR
27885 ['] LCD_WrC IS EMIT \ redirects EMIT
27886 $10 BASE ! \ change BASE to hexadecimal
27887 CR ." $" 2 U.R \ print IR_RC5 code
27888 ['] (CR) IS CR \ restore CR
27889 ['] (EMIT) IS EMIT \ restore EMIT
27890 HI2LO \ switch from FORTH to assembler
27891 \ ------------------------------\
27892 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
27893 \ ------------------------------\
27894 MOV @PSP+,&BASE \ restore variable BASE
27895 RETI \ CPU is ON, GIE is OFF
27900 \ ------------------------------\
27901 \ TB0CTL = %0000 0010 1001 0100\$3C0
27902 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27903 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27904 \ -- \ID input divider \ 10 = /4
27905 \ -- \MC Mode Control \ 01 = up to TB0CCR0
27906 \ - \TBCLR TimerB Clear
27909 \ --------------------------------\\
27910 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27911 \ -- \CM Capture Mode
27916 \ --- \OUTMOD \ 011 = set/reset
27922 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
27924 \ ------------------------------\
27925 \ set TimerB to make 50kHz PWM \
27926 \ ------------------------------\
27927 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27928 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
27929 \ ------------------------------\
27930 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
27931 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
27932 \ ------------------------------\
27933 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27934 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
27935 \ ------------------------------\
27936 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27937 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
27938 \ ------------------------------\
27939 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
27940 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
27941 \ ------------------------------\
27942 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
27943 \ ------------------------------\
27944 \ set TimerB to generate PWM for LCD_Vo
27945 \ ------------------------------\
27946 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
27947 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
27948 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27949 \ ------------------------------\
27950 BIS.B #LCDVo,&LCDVo_DIR \
27951 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
27952 \ ------------------------------\
27953 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27954 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27955 \ ------------------------------\
27956 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27957 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27958 \ ------------------------------\
27959 \ WDT interval init part \
27960 \ ------------------------------\
27961 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
27962 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
27963 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
27964 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
27965 \ ------------------------------\
27967 \ ------------------------------\
27968 BIS.B #RC5,&IR_IE \ enable RC5_Int
27969 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27970 \ ------------------------------\
27971 \ init interrupt vectors
27972 \ ------------------------------\
27973 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
27974 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27975 \ ------------------------------\
27976 \ define LPM mode for ACCEPT \
27977 \ ------------------------------\
27978 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27979 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27980 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27982 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
27984 \ ------------------------------\
27986 \ ------------------------------\
27987 $03E8 20_US \ 1- wait 20 ms
27988 $03 TOP_LCD \ 2- send DB5=DB4=1
27989 $CD 20_US \ 3- wait 4,1 ms
27990 $03 TOP_LCD \ 4- send again DB5=DB4=1
27991 $5 20_US \ 5- wait 0,1 ms
27992 $03 TOP_LCD \ 6- send again again DB5=DB4=1
27993 $2 20_US \ wait 40 us = LCD cycle
27994 $02 TOP_LCD \ 7- send DB5=1 DB4=0
27995 $2 20_US \ wait 40 us = LCD cycle
27996 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27997 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27998 LCD_Clear \ 10- "LCD_Clear"
27999 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28000 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28001 LCD_Clear \ 10- "LCD_Clear"
28002 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28003 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28005 ['] (CR) IS CR \ ' (CR) is CR
28006 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
28008 ." RC5toLCD is running. Type STOP to quit"
28009 \ NOECHO \ uncomment to run this app without terminal connexion
28010 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
28011 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
28015 : STOP \ stops multitasking, must to be used before downloading app
28016 ['] (WARM) IS WARM \ remove START app from FORTH init process
28017 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
28025 CODE MAX \ n1 n2 -- n3 signed maximum
28026 CMP @PSP,TOS \ n2-n1
28027 S< ?GOTO FW1 \ n2<n1
28033 CODE MIN \ n1 n2 -- n3 signed minimum
28034 CMP @PSP,TOS \ n2-n1
28035 S< ?GOTO BW1 \ n2<n1
28041 : U.R \ u n -- display u unsigned in n width (n >= 2)
28043 R> OVER - 0 MAX SPACES TYPE
28047 CODE 20_US \ n -- n * 20 us
28048 BEGIN \ 3 cycles loop + 6~
28049 \ MOV #5,W \ 3 MCLK = 1 MHz
28050 \ MOV #23,W \ 3 MCLK = 4 MHz
28051 MOV #51,W \ 3 MCLK = 8 MHz
28052 \ MOV #104,W \ 3 MCLK = 16 MHz
28053 \ MOV #158,W \ 3 MCLK = 24 MHz
28054 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
28064 CODE TOP_LCD \ LCD Sample
28065 \ \ if write : %xxxxWWWW --
28066 \ \ if read : -- %0000RRRR
28067 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28068 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28069 0= IF \ write LCD bits pattern
28070 AND.B #LCD_DB,TOS \
28071 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28072 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28075 THEN \ read LCD bits pattern
28078 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28079 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28080 AND.B #LCD_DB,TOS \
28085 CODE LCD_W \ byte -- write byte to LCD
28087 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28088 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28089 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28090 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28091 COLON \ high level word starts here
28092 TOP_LCD 2 20_US \ write high nibble first
28097 CODE LCD_WrC \ char -- Write Char
28098 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28103 CODE LCD_WrF \ func -- Write Fonction
28104 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28110 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
28115 $02 LCD_WrF 100 20_us
28119 \ : LCD_Entry_set $04 OR LCD_WrF ;
28121 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
28123 \ : LCD_Display_Shift $10 OR LCD_WrF ;
28125 \ : LCD_Fn_Set $20 OR LCD_WrF ;
28127 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
28129 \ : LCD_Goto $80 OR LCD_WrF ;
28131 \ CODE LCD_R \ -- byte read byte from LCD
28132 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28133 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28134 \ COLON \ starts a FORTH word
28135 \ TOP_LCD 2 20_us \ -- %0000HHHH
28136 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28137 \ HI2LO \ switch from FORTH to assembler
28138 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28139 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28140 \ MOV @RSP+,IP \ restore IP saved by COLON
28145 \ CODE LCD_RdS \ -- status Read Status
28146 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28151 \ CODE LCD_RdC \ -- char Read Char
28152 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28157 \ -------------+------+------+------+------++---+---+---+---+---------+
28158 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
28159 \ -------------+------+------+------+------++---+---+---+---+---------+
28160 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
28161 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
28162 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
28163 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
28164 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
28165 \ -------------+------+------+------+------++---+---+---+---+---------+
28168 \ ******************************\
28169 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28170 \ ******************************\
28171 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
28172 \ ------------------------------\
28173 \ define LPM mode for ACCEPT \
28174 \ ------------------------------\
28175 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28176 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28177 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28178 BIT.B #SW2,&SW2_IN \ test switch S2
28179 0= IF \ case of switch S2 pressed
28180 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
28182 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
28185 BIT.B #SW1,&SW1_IN \ test switch S1 input
28186 0= IF \ case of Switch S1 pressed
28187 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
28189 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
28193 RETI \ CPU is ON, GIE is OFF
28198 \ ------------------------------\
28199 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28200 \ ******************************\
28201 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28202 \ ******************************\
28203 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28204 \ \ SMclock = 8|16|24 MHz
28205 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
28206 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
28207 \ \ SR(9)=new Toggle bit memory (ADD on)
28208 \ ------------------------------\
28209 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
28210 \ ------------------------------\
28211 \ define LPM mode for ACCEPT \
28212 \ ------------------------------\
28213 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28214 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28215 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28216 \ ------------------------------\
28217 \ RC5_FirstStartBitHalfCycle: \
28218 \ ------------------------------\
28219 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
28220 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
28221 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
28222 MOV #1778,X \ RC5_Period in us
28223 MOV #14,W \ count of loop
28225 \ ------------------------------\
28226 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
28227 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
28228 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
28229 \ RC5_Compute_3/4_Period: \ |
28230 RRUM #1,X \ X=1/2 cycle |
28234 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
28235 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
28237 \ ------------------------------\
28238 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
28239 \ ------------------------------\
28240 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28241 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
28242 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28243 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28244 SUB #1,W \ decrement count loop
28245 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
28246 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28247 0<> WHILE \ ----> out of loop ----+
28248 \ RC5_compute_7/4_Time_out: \ |
28249 ADD X,Y \ | out of bound = 7/4 period
28250 \ RC5_WaitHalfCycleP1.2_IFG: \ |
28252 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
28253 0>= IF \ | if cycle time out of bound
28254 BIC #$30,&TA0CTL \ | stop timer_A0
28255 RETI \ | then quit to do nothing
28257 \ ------------------------------\ |
28258 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
28260 MOV &TA0R,X \ | | get new RC5_period value
28261 REPEAT \ ----> loop back --+ |
28262 \ ------------------------------\ |
28263 \ RC5_SampleEndOf: \ <---------------------+
28264 \ ------------------------------\
28265 BIC #$30,&TA0CTL \ stop timer_A0
28266 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
28267 \ ******************************\
28268 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28269 \ ******************************\
28270 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
28271 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
28272 XOR IP,X \ (new XOR old) Toggle bit (13)
28273 BIT #BIT13,X \ X(13) = New_RC5_command
28274 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
28276 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
28277 \ ******************************\
28278 \ RC5_ComputeNewRC5word \
28279 \ ******************************\
28281 MOV &BASE,2(PSP) \ save variable BASE before use
28282 MOV TOS,0(PSP) \ save TOS before use
28283 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
28284 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
28285 \ ******************************\
28286 \ RC5_ComputeC6bit \
28287 \ ******************************\
28288 BIT #$4000,IP \ test /C6 bit in IP
28289 0= IF BIS #$40,TOS \ set C6 bit in S
28290 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
28291 \ ******************************\
28292 \ RC5_CommandByteIsDone \ RC5_code --
28293 \ ******************************\
28295 \ ------------------------------\
28296 \ Display IR_RC5 code \
28297 \ ------------------------------\
28298 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
28299 \ ------------------------------\
28300 LO2HI \ switch from assembler to FORTH
28301 ['] LCD_CLEAR IS CR \ redirects CR
28302 ['] LCD_WrC IS EMIT \ redirects EMIT
28303 $10 BASE ! \ change BASE to hexadecimal
28304 CR ." $" 2 U.R \ print IR_RC5 code
28305 ['] (CR) IS CR \ restore CR
28306 ['] (EMIT) IS EMIT \ restore EMIT
28307 HI2LO \ switch from FORTH to assembler
28308 \ ------------------------------\
28309 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
28310 \ ------------------------------\
28311 MOV @PSP+,&BASE \ restore variable BASE
28312 RETI \ CPU is ON, GIE is OFF
28317 \ ------------------------------\
28318 \ TB0CTL = %0000 0010 1001 0100\$3C0
28319 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28320 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28321 \ -- \ID input divider \ 10 = /4
28322 \ -- \MC Mode Control \ 01 = up to TB0CCR0
28323 \ - \TBCLR TimerB Clear
28326 \ --------------------------------\\
28327 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28328 \ -- \CM Capture Mode
28333 \ --- \OUTMOD \ 011 = set/reset
28339 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
28341 \ ------------------------------\
28342 \ set TimerB to make 50kHz PWM \
28343 \ ------------------------------\
28344 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28345 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
28346 \ ------------------------------\
28347 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28348 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
28349 \ ------------------------------\
28350 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28351 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
28352 \ ------------------------------\
28353 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28354 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
28355 \ ------------------------------\
28356 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28357 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
28358 \ ------------------------------\
28359 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
28360 \ ------------------------------\
28361 \ set TimerB to generate PWM for LCD_Vo
28362 \ ------------------------------\
28363 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
28364 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
28365 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28366 \ ------------------------------\
28367 BIS.B #LCDVo,&LCDVo_DIR \
28368 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
28369 \ ------------------------------\
28370 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28371 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28372 \ ------------------------------\
28373 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28374 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28375 \ ------------------------------\
28376 \ WDT interval init part \
28377 \ ------------------------------\
28378 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
28379 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
28380 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
28381 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
28382 \ ------------------------------\
28384 \ ------------------------------\
28385 BIS.B #RC5,&IR_IE \ enable RC5_Int
28386 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28387 \ ------------------------------\
28388 \ init interrupt vectors
28389 \ ------------------------------\
28390 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
28391 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28392 \ ------------------------------\
28393 \ define LPM mode for ACCEPT \
28394 \ ------------------------------\
28395 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28396 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28397 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28399 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
28401 \ ------------------------------\
28403 \ ------------------------------\
28404 $03E8 20_US \ 1- wait 20 ms
28405 $03 TOP_LCD \ 2- send DB5=DB4=1
28406 $CD 20_US \ 3- wait 4,1 ms
28407 $03 TOP_LCD \ 4- send again DB5=DB4=1
28408 $5 20_US \ 5- wait 0,1 ms
28409 $03 TOP_LCD \ 6- send again again DB5=DB4=1
28410 $2 20_US \ wait 40 us = LCD cycle
28411 $02 TOP_LCD \ 7- send DB5=1 DB4=0
28412 $2 20_US \ wait 40 us = LCD cycle
28413 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28414 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28415 LCD_Clear \ 10- "LCD_Clear"
28416 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28417 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28418 LCD_Clear \ 10- "LCD_Clear"
28419 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28420 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28422 ['] (CR) IS CR \ ' (CR) is CR
28423 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
28425 ." RC5toLCD is running. Type STOP to quit"
28426 \ NOECHO \ uncomment to run this app without terminal connexion
28427 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
28428 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
28432 : STOP \ stops multitasking, must to be used before downloading app
28433 ['] (WARM) IS WARM \ remove START app from FORTH init process
28434 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
28442 CODE MAX \ n1 n2 -- n3 signed maximum
28443 CMP @PSP,TOS \ n2-n1
28444 S< ?GOTO FW1 \ n2<n1
28450 CODE MIN \ n1 n2 -- n3 signed minimum
28451 CMP @PSP,TOS \ n2-n1
28452 S< ?GOTO BW1 \ n2<n1
28458 : U.R \ u n -- display u unsigned in n width (n >= 2)
28460 R> OVER - 0 MAX SPACES TYPE
28464 CODE 20_US \ n -- n * 20 us
28465 BEGIN \ 3 cycles loop + 6~
28466 \ MOV #5,W \ 3 MCLK = 1 MHz
28467 \ MOV #23,W \ 3 MCLK = 4 MHz
28468 MOV #51,W \ 3 MCLK = 8 MHz
28469 \ MOV #104,W \ 3 MCLK = 16 MHz
28470 \ MOV #158,W \ 3 MCLK = 24 MHz
28471 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
28481 CODE TOP_LCD \ LCD Sample
28482 \ \ if write : %xxxxWWWW --
28483 \ \ if read : -- %0000RRRR
28484 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28485 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28486 0= IF \ write LCD bits pattern
28487 AND.B #LCD_DB,TOS \
28488 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28489 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28492 THEN \ read LCD bits pattern
28495 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28496 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28497 AND.B #LCD_DB,TOS \
28502 CODE LCD_W \ byte -- write byte to LCD
28504 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28505 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28506 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28507 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28508 COLON \ high level word starts here
28509 TOP_LCD 2 20_US \ write high nibble first
28514 CODE LCD_WrC \ char -- Write Char
28515 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28520 CODE LCD_WrF \ func -- Write Fonction
28521 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28527 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
28532 $02 LCD_WrF 100 20_us
28536 \ : LCD_Entry_set $04 OR LCD_WrF ;
28538 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
28540 \ : LCD_Display_Shift $10 OR LCD_WrF ;
28542 \ : LCD_Fn_Set $20 OR LCD_WrF ;
28544 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
28546 \ : LCD_Goto $80 OR LCD_WrF ;
28548 \ CODE LCD_R \ -- byte read byte from LCD
28549 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28550 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28551 \ COLON \ starts a FORTH word
28552 \ TOP_LCD 2 20_us \ -- %0000HHHH
28553 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28554 \ HI2LO \ switch from FORTH to assembler
28555 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28556 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28557 \ MOV @RSP+,IP \ restore IP saved by COLON
28562 \ CODE LCD_RdS \ -- status Read Status
28563 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28568 \ CODE LCD_RdC \ -- char Read Char
28569 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28574 \ -------------+------+------+------+------++---+---+---+---+---------+
28575 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
28576 \ -------------+------+------+------+------++---+---+---+---+---------+
28577 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
28578 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
28579 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
28580 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
28581 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
28582 \ -------------+------+------+------+------++---+---+---+---+---------+
28585 \ ******************************\
28586 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28587 \ ******************************\
28588 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
28589 \ ------------------------------\
28590 \ define LPM mode for ACCEPT \
28591 \ ------------------------------\
28592 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28593 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28594 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28595 BIT.B #SW2,&SW2_IN \ test switch S2
28596 0= IF \ case of switch S2 pressed
28597 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
28599 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
28602 BIT.B #SW1,&SW1_IN \ test switch S1 input
28603 0= IF \ case of Switch S1 pressed
28604 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
28606 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
28610 RETI \ CPU is ON, GIE is OFF
28615 \ ------------------------------\
28616 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28617 \ ******************************\
28618 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28619 \ ******************************\
28620 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28621 \ \ SMclock = 8|16|24 MHz
28622 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
28623 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
28624 \ \ SR(9)=new Toggle bit memory (ADD on)
28625 \ ------------------------------\
28626 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
28627 \ ------------------------------\
28628 \ define LPM mode for ACCEPT \
28629 \ ------------------------------\
28630 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28631 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28632 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28633 \ ------------------------------\
28634 \ RC5_FirstStartBitHalfCycle: \
28635 \ ------------------------------\
28636 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
28637 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
28638 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
28639 MOV #1778,X \ RC5_Period in us
28640 MOV #14,W \ count of loop
28642 \ ------------------------------\
28643 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
28644 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
28645 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
28646 \ RC5_Compute_3/4_Period: \ |
28647 RRUM #1,X \ X=1/2 cycle |
28651 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
28652 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
28654 \ ------------------------------\
28655 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
28656 \ ------------------------------\
28657 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28658 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
28659 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28660 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28661 SUB #1,W \ decrement count loop
28662 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
28663 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28664 0<> WHILE \ ----> out of loop ----+
28665 \ RC5_compute_7/4_Time_out: \ |
28666 ADD X,Y \ | out of bound = 7/4 period
28667 \ RC5_WaitHalfCycleP1.2_IFG: \ |
28669 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
28670 0>= IF \ | if cycle time out of bound
28671 BIC #$30,&TA0CTL \ | stop timer_A0
28672 RETI \ | then quit to do nothing
28674 \ ------------------------------\ |
28675 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
28677 MOV &TA0R,X \ | | get new RC5_period value
28678 REPEAT \ ----> loop back --+ |
28679 \ ------------------------------\ |
28680 \ RC5_SampleEndOf: \ <---------------------+
28681 \ ------------------------------\
28682 BIC #$30,&TA0CTL \ stop timer_A0
28683 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
28684 \ ******************************\
28685 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28686 \ ******************************\
28687 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
28688 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
28689 XOR IP,X \ (new XOR old) Toggle bit (13)
28690 BIT #BIT13,X \ X(13) = New_RC5_command
28691 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
28693 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
28694 \ ******************************\
28695 \ RC5_ComputeNewRC5word \
28696 \ ******************************\
28698 MOV &BASE,2(PSP) \ save variable BASE before use
28699 MOV TOS,0(PSP) \ save TOS before use
28700 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
28701 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
28702 \ ******************************\
28703 \ RC5_ComputeC6bit \
28704 \ ******************************\
28705 BIT #$4000,IP \ test /C6 bit in IP
28706 0= IF BIS #$40,TOS \ set C6 bit in S
28707 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
28708 \ ******************************\
28709 \ RC5_CommandByteIsDone \ RC5_code --
28710 \ ******************************\
28712 \ ------------------------------\
28713 \ Display IR_RC5 code \
28714 \ ------------------------------\
28715 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
28716 \ ------------------------------\
28717 LO2HI \ switch from assembler to FORTH
28718 ['] LCD_CLEAR IS CR \ redirects CR
28719 ['] LCD_WrC IS EMIT \ redirects EMIT
28720 $10 BASE ! \ change BASE to hexadecimal
28721 CR ." $" 2 U.R \ print IR_RC5 code
28722 ['] (CR) IS CR \ restore CR
28723 ['] (EMIT) IS EMIT \ restore EMIT
28724 HI2LO \ switch from FORTH to assembler
28725 \ ------------------------------\
28726 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
28727 \ ------------------------------\
28728 MOV @PSP+,&BASE \ restore variable BASE
28729 RETI \ CPU is ON, GIE is OFF
28734 \ ------------------------------\
28735 \ TB0CTL = %0000 0010 1001 0100\$3C0
28736 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28737 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28738 \ -- \ID input divider \ 10 = /4
28739 \ -- \MC Mode Control \ 01 = up to TB0CCR0
28740 \ - \TBCLR TimerB Clear
28743 \ --------------------------------\\
28744 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28745 \ -- \CM Capture Mode
28750 \ --- \OUTMOD \ 011 = set/reset
28756 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
28758 \ ------------------------------\
28759 \ set TimerB to make 50kHz PWM \
28760 \ ------------------------------\
28761 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28762 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
28763 \ ------------------------------\
28764 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
28765 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
28766 \ ------------------------------\
28767 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28768 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
28769 \ ------------------------------\
28770 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28771 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
28772 \ ------------------------------\
28773 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
28774 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
28775 \ ------------------------------\
28776 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
28777 \ ------------------------------\
28778 \ set TimerB to generate PWM for LCD_Vo
28779 \ ------------------------------\
28780 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
28781 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
28782 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28783 \ ------------------------------\
28784 BIS.B #LCDVo,&LCDVo_DIR \
28785 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
28786 \ ------------------------------\
28787 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28788 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28789 \ ------------------------------\
28790 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28791 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28792 \ ------------------------------\
28793 \ WDT interval init part \
28794 \ ------------------------------\
28795 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
28796 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
28797 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
28798 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
28799 \ ------------------------------\
28801 \ ------------------------------\
28802 BIS.B #RC5,&IR_IE \ enable RC5_Int
28803 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28804 \ ------------------------------\
28805 \ init interrupt vectors
28806 \ ------------------------------\
28807 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
28808 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28809 \ ------------------------------\
28810 \ define LPM mode for ACCEPT \
28811 \ ------------------------------\
28812 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28813 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28814 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28816 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
28818 \ ------------------------------\
28820 \ ------------------------------\
28821 $03E8 20_US \ 1- wait 20 ms
28822 $03 TOP_LCD \ 2- send DB5=DB4=1
28823 $CD 20_US \ 3- wait 4,1 ms
28824 $03 TOP_LCD \ 4- send again DB5=DB4=1
28825 $5 20_US \ 5- wait 0,1 ms
28826 $03 TOP_LCD \ 6- send again again DB5=DB4=1
28827 $2 20_US \ wait 40 us = LCD cycle
28828 $02 TOP_LCD \ 7- send DB5=1 DB4=0
28829 $2 20_US \ wait 40 us = LCD cycle
28830 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28831 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28832 LCD_Clear \ 10- "LCD_Clear"
28833 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28834 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28835 LCD_Clear \ 10- "LCD_Clear"
28836 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28837 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28839 ['] (CR) IS CR \ ' (CR) is CR
28840 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
28842 ." RC5toLCD is running. Type STOP to quit"
28843 \ NOECHO \ uncomment to run this app without terminal connexion
28844 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
28845 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
28849 : STOP \ stops multitasking, must to be used before downloading app
28850 ['] (WARM) IS WARM \ remove START app from FORTH init process
28851 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
28859 CODE MAX \ n1 n2 -- n3 signed maximum
28860 CMP @PSP,TOS \ n2-n1
28861 S< ?GOTO FW1 \ n2<n1
28867 CODE MIN \ n1 n2 -- n3 signed minimum
28868 CMP @PSP,TOS \ n2-n1
28869 S< ?GOTO BW1 \ n2<n1
28875 : U.R \ u n -- display u unsigned in n width (n >= 2)
28877 R> OVER - 0 MAX SPACES TYPE
28881 CODE 20_US \ n -- n * 20 us
28882 BEGIN \ 3 cycles loop + 6~
28883 \ MOV #5,W \ 3 MCLK = 1 MHz
28884 \ MOV #23,W \ 3 MCLK = 4 MHz
28885 MOV #51,W \ 3 MCLK = 8 MHz
28886 \ MOV #104,W \ 3 MCLK = 16 MHz
28887 \ MOV #158,W \ 3 MCLK = 24 MHz
28888 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
28898 CODE TOP_LCD \ LCD Sample
28899 \ \ if write : %xxxxWWWW --
28900 \ \ if read : -- %0000RRRR
28901 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28902 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28903 0= IF \ write LCD bits pattern
28904 AND.B #LCD_DB,TOS \
28905 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28906 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28909 THEN \ read LCD bits pattern
28912 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28913 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28914 AND.B #LCD_DB,TOS \
28919 CODE LCD_W \ byte -- write byte to LCD
28921 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
28922 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
28923 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28924 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28925 COLON \ high level word starts here
28926 TOP_LCD 2 20_US \ write high nibble first
28931 CODE LCD_WrC \ char -- Write Char
28932 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28937 CODE LCD_WrF \ func -- Write Fonction
28938 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28944 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
28949 $02 LCD_WrF 100 20_us
28953 \ : LCD_Entry_set $04 OR LCD_WrF ;
28955 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
28957 \ : LCD_Display_Shift $10 OR LCD_WrF ;
28959 \ : LCD_Fn_Set $20 OR LCD_WrF ;
28961 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
28963 \ : LCD_Goto $80 OR LCD_WrF ;
28965 \ CODE LCD_R \ -- byte read byte from LCD
28966 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28967 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28968 \ COLON \ starts a FORTH word
28969 \ TOP_LCD 2 20_us \ -- %0000HHHH
28970 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
28971 \ HI2LO \ switch from FORTH to assembler
28972 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
28973 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
28974 \ MOV @RSP+,IP \ restore IP saved by COLON
28979 \ CODE LCD_RdS \ -- status Read Status
28980 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28985 \ CODE LCD_RdC \ -- char Read Char
28986 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28991 \ -------------+------+------+------+------++---+---+---+---+---------+
28992 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
28993 \ -------------+------+------+------+------++---+---+---+---+---------+
28994 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
28995 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
28996 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
28997 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
28998 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
28999 \ -------------+------+------+------+------++---+---+---+---+---------+
29002 \ ******************************\
29003 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29004 \ ******************************\
29005 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
29006 \ ------------------------------\
29007 \ define LPM mode for ACCEPT \
29008 \ ------------------------------\
29009 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29010 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29011 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29012 BIT.B #SW2,&SW2_IN \ test switch S2
29013 0= IF \ case of switch S2 pressed
29014 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
29016 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
29019 BIT.B #SW1,&SW1_IN \ test switch S1 input
29020 0= IF \ case of Switch S1 pressed
29021 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
29023 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
29027 RETI \ CPU is ON, GIE is OFF
29032 \ ------------------------------\
29033 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29034 \ ******************************\
29035 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29036 \ ******************************\
29037 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29038 \ \ SMclock = 8|16|24 MHz
29039 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
29040 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
29041 \ \ SR(9)=new Toggle bit memory (ADD on)
29042 \ ------------------------------\
29043 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
29044 \ ------------------------------\
29045 \ define LPM mode for ACCEPT \
29046 \ ------------------------------\
29047 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29048 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29049 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29050 \ ------------------------------\
29051 \ RC5_FirstStartBitHalfCycle: \
29052 \ ------------------------------\
29053 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
29054 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
29055 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
29056 MOV #1778,X \ RC5_Period in us
29057 MOV #14,W \ count of loop
29059 \ ------------------------------\
29060 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
29061 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
29062 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
29063 \ RC5_Compute_3/4_Period: \ |
29064 RRUM #1,X \ X=1/2 cycle |
29068 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
29069 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
29071 \ ------------------------------\
29072 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
29073 \ ------------------------------\
29074 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29075 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
29076 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29077 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29078 SUB #1,W \ decrement count loop
29079 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
29080 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29081 0<> WHILE \ ----> out of loop ----+
29082 \ RC5_compute_7/4_Time_out: \ |
29083 ADD X,Y \ | out of bound = 7/4 period
29084 \ RC5_WaitHalfCycleP1.2_IFG: \ |
29086 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
29087 0>= IF \ | if cycle time out of bound
29088 BIC #$30,&TA0CTL \ | stop timer_A0
29089 RETI \ | then quit to do nothing
29091 \ ------------------------------\ |
29092 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
29094 MOV &TA0R,X \ | | get new RC5_period value
29095 REPEAT \ ----> loop back --+ |
29096 \ ------------------------------\ |
29097 \ RC5_SampleEndOf: \ <---------------------+
29098 \ ------------------------------\
29099 BIC #$30,&TA0CTL \ stop timer_A0
29100 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
29101 \ ******************************\
29102 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29103 \ ******************************\
29104 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
29105 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
29106 XOR IP,X \ (new XOR old) Toggle bit (13)
29107 BIT #BIT13,X \ X(13) = New_RC5_command
29108 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
29110 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
29111 \ ******************************\
29112 \ RC5_ComputeNewRC5word \
29113 \ ******************************\
29115 MOV &BASE,2(PSP) \ save variable BASE before use
29116 MOV TOS,0(PSP) \ save TOS before use
29117 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
29118 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
29119 \ ******************************\
29120 \ RC5_ComputeC6bit \
29121 \ ******************************\
29122 BIT #$4000,IP \ test /C6 bit in IP
29123 0= IF BIS #$40,TOS \ set C6 bit in S
29124 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
29125 \ ******************************\
29126 \ RC5_CommandByteIsDone \ RC5_code --
29127 \ ******************************\
29129 \ ------------------------------\
29130 \ Display IR_RC5 code \
29131 \ ------------------------------\
29132 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
29133 \ ------------------------------\
29134 LO2HI \ switch from assembler to FORTH
29135 ['] LCD_CLEAR IS CR \ redirects CR
29136 ['] LCD_WrC IS EMIT \ redirects EMIT
29137 $10 BASE ! \ change BASE to hexadecimal
29138 CR ." $" 2 U.R \ print IR_RC5 code
29139 ['] (CR) IS CR \ restore CR
29140 ['] (EMIT) IS EMIT \ restore EMIT
29141 HI2LO \ switch from FORTH to assembler
29142 \ ------------------------------\
29143 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
29144 \ ------------------------------\
29145 MOV @PSP+,&BASE \ restore variable BASE
29146 RETI \ CPU is ON, GIE is OFF
29151 \ ------------------------------\
29152 \ TB0CTL = %0000 0010 1001 0100\$3C0
29153 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29154 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29155 \ -- \ID input divider \ 10 = /4
29156 \ -- \MC Mode Control \ 01 = up to TB0CCR0
29157 \ - \TBCLR TimerB Clear
29160 \ --------------------------------\\
29161 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29162 \ -- \CM Capture Mode
29167 \ --- \OUTMOD \ 011 = set/reset
29173 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
29175 \ ------------------------------\
29176 \ set TimerB to make 50kHz PWM \
29177 \ ------------------------------\
29178 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29179 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
29180 \ ------------------------------\
29181 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29182 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
29183 \ ------------------------------\
29184 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29185 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
29186 \ ------------------------------\
29187 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29188 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
29189 \ ------------------------------\
29190 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29191 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
29192 \ ------------------------------\
29193 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
29194 \ ------------------------------\
29195 \ set TimerB to generate PWM for LCD_Vo
29196 \ ------------------------------\
29197 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
29198 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
29199 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29200 \ ------------------------------\
29201 BIS.B #LCDVo,&LCDVo_DIR \
29202 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
29203 \ ------------------------------\
29204 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29205 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29206 \ ------------------------------\
29207 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29208 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29209 \ ------------------------------\
29210 \ WDT interval init part \
29211 \ ------------------------------\
29212 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
29213 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
29214 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
29215 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
29216 \ ------------------------------\
29218 \ ------------------------------\
29219 BIS.B #RC5,&IR_IE \ enable RC5_Int
29220 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29221 \ ------------------------------\
29222 \ init interrupt vectors
29223 \ ------------------------------\
29224 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
29225 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29226 \ ------------------------------\
29227 \ define LPM mode for ACCEPT \
29228 \ ------------------------------\
29229 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29230 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29231 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29233 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
29235 \ ------------------------------\
29237 \ ------------------------------\
29238 $03E8 20_US \ 1- wait 20 ms
29239 $03 TOP_LCD \ 2- send DB5=DB4=1
29240 $CD 20_US \ 3- wait 4,1 ms
29241 $03 TOP_LCD \ 4- send again DB5=DB4=1
29242 $5 20_US \ 5- wait 0,1 ms
29243 $03 TOP_LCD \ 6- send again again DB5=DB4=1
29244 $2 20_US \ wait 40 us = LCD cycle
29245 $02 TOP_LCD \ 7- send DB5=1 DB4=0
29246 $2 20_US \ wait 40 us = LCD cycle
29247 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29248 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29249 LCD_Clear \ 10- "LCD_Clear"
29250 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29251 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29252 LCD_Clear \ 10- "LCD_Clear"
29253 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29254 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29256 ['] (CR) IS CR \ ' (CR) is CR
29257 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
29259 ." RC5toLCD is running. Type STOP to quit"
29260 \ NOECHO \ uncomment to run this app without terminal connexion
29261 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
29262 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
29266 : STOP \ stops multitasking, must to be used before downloading app
29267 ['] (WARM) IS WARM \ remove START app from FORTH init process
29268 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
29276 CODE MAX \ n1 n2 -- n3 signed maximum
29277 CMP @PSP,TOS \ n2-n1
29278 S< ?GOTO FW1 \ n2<n1
29284 CODE MIN \ n1 n2 -- n3 signed minimum
29285 CMP @PSP,TOS \ n2-n1
29286 S< ?GOTO BW1 \ n2<n1
29292 : U.R \ u n -- display u unsigned in n width (n >= 2)
29294 R> OVER - 0 MAX SPACES TYPE
29298 CODE 20_US \ n -- n * 20 us
29299 BEGIN \ 3 cycles loop + 6~
29300 \ MOV #5,W \ 3 MCLK = 1 MHz
29301 \ MOV #23,W \ 3 MCLK = 4 MHz
29302 MOV #51,W \ 3 MCLK = 8 MHz
29303 \ MOV #104,W \ 3 MCLK = 16 MHz
29304 \ MOV #158,W \ 3 MCLK = 24 MHz
29305 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
29315 CODE TOP_LCD \ LCD Sample
29316 \ \ if write : %xxxxWWWW --
29317 \ \ if read : -- %0000RRRR
29318 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29319 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29320 0= IF \ write LCD bits pattern
29321 AND.B #LCD_DB,TOS \
29322 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29323 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29326 THEN \ read LCD bits pattern
29329 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29330 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29331 AND.B #LCD_DB,TOS \
29336 CODE LCD_W \ byte -- write byte to LCD
29338 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29339 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29340 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29341 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29342 COLON \ high level word starts here
29343 TOP_LCD 2 20_US \ write high nibble first
29348 CODE LCD_WrC \ char -- Write Char
29349 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29354 CODE LCD_WrF \ func -- Write Fonction
29355 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29361 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
29366 $02 LCD_WrF 100 20_us
29370 \ : LCD_Entry_set $04 OR LCD_WrF ;
29372 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
29374 \ : LCD_Display_Shift $10 OR LCD_WrF ;
29376 \ : LCD_Fn_Set $20 OR LCD_WrF ;
29378 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
29380 \ : LCD_Goto $80 OR LCD_WrF ;
29382 \ CODE LCD_R \ -- byte read byte from LCD
29383 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29384 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29385 \ COLON \ starts a FORTH word
29386 \ TOP_LCD 2 20_us \ -- %0000HHHH
29387 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29388 \ HI2LO \ switch from FORTH to assembler
29389 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29390 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29391 \ MOV @RSP+,IP \ restore IP saved by COLON
29396 \ CODE LCD_RdS \ -- status Read Status
29397 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29402 \ CODE LCD_RdC \ -- char Read Char
29403 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29408 \ -------------+------+------+------+------++---+---+---+---+---------+
29409 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
29410 \ -------------+------+------+------+------++---+---+---+---+---------+
29411 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
29412 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
29413 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
29414 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
29415 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
29416 \ -------------+------+------+------+------++---+---+---+---+---------+
29419 \ ******************************\
29420 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29421 \ ******************************\
29422 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
29423 \ ------------------------------\
29424 \ define LPM mode for ACCEPT \
29425 \ ------------------------------\
29426 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29427 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29428 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29429 BIT.B #SW2,&SW2_IN \ test switch S2
29430 0= IF \ case of switch S2 pressed
29431 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
29433 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
29436 BIT.B #SW1,&SW1_IN \ test switch S1 input
29437 0= IF \ case of Switch S1 pressed
29438 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
29440 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
29444 RETI \ CPU is ON, GIE is OFF
29449 \ ------------------------------\
29450 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29451 \ ******************************\
29452 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29453 \ ******************************\
29454 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29455 \ \ SMclock = 8|16|24 MHz
29456 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
29457 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
29458 \ \ SR(9)=new Toggle bit memory (ADD on)
29459 \ ------------------------------\
29460 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
29461 \ ------------------------------\
29462 \ define LPM mode for ACCEPT \
29463 \ ------------------------------\
29464 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29465 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29466 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29467 \ ------------------------------\
29468 \ RC5_FirstStartBitHalfCycle: \
29469 \ ------------------------------\
29470 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
29471 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
29472 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
29473 MOV #1778,X \ RC5_Period in us
29474 MOV #14,W \ count of loop
29476 \ ------------------------------\
29477 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
29478 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
29479 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
29480 \ RC5_Compute_3/4_Period: \ |
29481 RRUM #1,X \ X=1/2 cycle |
29485 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
29486 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
29488 \ ------------------------------\
29489 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
29490 \ ------------------------------\
29491 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29492 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
29493 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29494 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29495 SUB #1,W \ decrement count loop
29496 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
29497 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29498 0<> WHILE \ ----> out of loop ----+
29499 \ RC5_compute_7/4_Time_out: \ |
29500 ADD X,Y \ | out of bound = 7/4 period
29501 \ RC5_WaitHalfCycleP1.2_IFG: \ |
29503 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
29504 0>= IF \ | if cycle time out of bound
29505 BIC #$30,&TA0CTL \ | stop timer_A0
29506 RETI \ | then quit to do nothing
29508 \ ------------------------------\ |
29509 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
29511 MOV &TA0R,X \ | | get new RC5_period value
29512 REPEAT \ ----> loop back --+ |
29513 \ ------------------------------\ |
29514 \ RC5_SampleEndOf: \ <---------------------+
29515 \ ------------------------------\
29516 BIC #$30,&TA0CTL \ stop timer_A0
29517 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
29518 \ ******************************\
29519 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29520 \ ******************************\
29521 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
29522 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
29523 XOR IP,X \ (new XOR old) Toggle bit (13)
29524 BIT #BIT13,X \ X(13) = New_RC5_command
29525 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
29527 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
29528 \ ******************************\
29529 \ RC5_ComputeNewRC5word \
29530 \ ******************************\
29532 MOV &BASE,2(PSP) \ save variable BASE before use
29533 MOV TOS,0(PSP) \ save TOS before use
29534 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
29535 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
29536 \ ******************************\
29537 \ RC5_ComputeC6bit \
29538 \ ******************************\
29539 BIT #$4000,IP \ test /C6 bit in IP
29540 0= IF BIS #$40,TOS \ set C6 bit in S
29541 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
29542 \ ******************************\
29543 \ RC5_CommandByteIsDone \ RC5_code --
29544 \ ******************************\
29546 \ ------------------------------\
29547 \ Display IR_RC5 code \
29548 \ ------------------------------\
29549 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
29550 \ ------------------------------\
29551 LO2HI \ switch from assembler to FORTH
29552 ['] LCD_CLEAR IS CR \ redirects CR
29553 ['] LCD_WrC IS EMIT \ redirects EMIT
29554 $10 BASE ! \ change BASE to hexadecimal
29555 CR ." $" 2 U.R \ print IR_RC5 code
29556 ['] (CR) IS CR \ restore CR
29557 ['] (EMIT) IS EMIT \ restore EMIT
29558 HI2LO \ switch from FORTH to assembler
29559 \ ------------------------------\
29560 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
29561 \ ------------------------------\
29562 MOV @PSP+,&BASE \ restore variable BASE
29563 RETI \ CPU is ON, GIE is OFF
29568 \ ------------------------------\
29569 \ TB0CTL = %0000 0010 1001 0100\$3C0
29570 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29571 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29572 \ -- \ID input divider \ 10 = /4
29573 \ -- \MC Mode Control \ 01 = up to TB0CCR0
29574 \ - \TBCLR TimerB Clear
29577 \ --------------------------------\\
29578 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29579 \ -- \CM Capture Mode
29584 \ --- \OUTMOD \ 011 = set/reset
29590 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
29592 \ ------------------------------\
29593 \ set TimerB to make 50kHz PWM \
29594 \ ------------------------------\
29595 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29596 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
29597 \ ------------------------------\
29598 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
29599 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
29600 \ ------------------------------\
29601 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29602 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
29603 \ ------------------------------\
29604 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29605 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
29606 \ ------------------------------\
29607 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
29608 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
29609 \ ------------------------------\
29610 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
29611 \ ------------------------------\
29612 \ set TimerB to generate PWM for LCD_Vo
29613 \ ------------------------------\
29614 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
29615 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
29616 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29617 \ ------------------------------\
29618 BIS.B #LCDVo,&LCDVo_DIR \
29619 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
29620 \ ------------------------------\
29621 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29622 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29623 \ ------------------------------\
29624 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29625 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29626 \ ------------------------------\
29627 \ WDT interval init part \
29628 \ ------------------------------\
29629 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
29630 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
29631 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
29632 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
29633 \ ------------------------------\
29635 \ ------------------------------\
29636 BIS.B #RC5,&IR_IE \ enable RC5_Int
29637 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29638 \ ------------------------------\
29639 \ init interrupt vectors
29640 \ ------------------------------\
29641 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
29642 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29643 \ ------------------------------\
29644 \ define LPM mode for ACCEPT \
29645 \ ------------------------------\
29646 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29647 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29648 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29650 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
29652 \ ------------------------------\
29654 \ ------------------------------\
29655 $03E8 20_US \ 1- wait 20 ms
29656 $03 TOP_LCD \ 2- send DB5=DB4=1
29657 $CD 20_US \ 3- wait 4,1 ms
29658 $03 TOP_LCD \ 4- send again DB5=DB4=1
29659 $5 20_US \ 5- wait 0,1 ms
29660 $03 TOP_LCD \ 6- send again again DB5=DB4=1
29661 $2 20_US \ wait 40 us = LCD cycle
29662 $02 TOP_LCD \ 7- send DB5=1 DB4=0
29663 $2 20_US \ wait 40 us = LCD cycle
29664 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29665 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29666 LCD_Clear \ 10- "LCD_Clear"
29667 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29668 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29669 LCD_Clear \ 10- "LCD_Clear"
29670 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29671 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29673 ['] (CR) IS CR \ ' (CR) is CR
29674 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
29676 ." RC5toLCD is running. Type STOP to quit"
29677 \ NOECHO \ uncomment to run this app without terminal connexion
29678 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
29679 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
29683 : STOP \ stops multitasking, must to be used before downloading app
29684 ['] (WARM) IS WARM \ remove START app from FORTH init process
29685 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
29693 CODE MAX \ n1 n2 -- n3 signed maximum
29694 CMP @PSP,TOS \ n2-n1
29695 S< ?GOTO FW1 \ n2<n1
29701 CODE MIN \ n1 n2 -- n3 signed minimum
29702 CMP @PSP,TOS \ n2-n1
29703 S< ?GOTO BW1 \ n2<n1
29709 : U.R \ u n -- display u unsigned in n width (n >= 2)
29711 R> OVER - 0 MAX SPACES TYPE
29715 CODE 20_US \ n -- n * 20 us
29716 BEGIN \ 3 cycles loop + 6~
29717 \ MOV #5,W \ 3 MCLK = 1 MHz
29718 \ MOV #23,W \ 3 MCLK = 4 MHz
29719 MOV #51,W \ 3 MCLK = 8 MHz
29720 \ MOV #104,W \ 3 MCLK = 16 MHz
29721 \ MOV #158,W \ 3 MCLK = 24 MHz
29722 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
29732 CODE TOP_LCD \ LCD Sample
29733 \ \ if write : %xxxxWWWW --
29734 \ \ if read : -- %0000RRRR
29735 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29736 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29737 0= IF \ write LCD bits pattern
29738 AND.B #LCD_DB,TOS \
29739 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29740 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29743 THEN \ read LCD bits pattern
29746 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29747 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29748 AND.B #LCD_DB,TOS \
29753 CODE LCD_W \ byte -- write byte to LCD
29755 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
29756 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
29757 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29758 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29759 COLON \ high level word starts here
29760 TOP_LCD 2 20_US \ write high nibble first
29765 CODE LCD_WrC \ char -- Write Char
29766 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29771 CODE LCD_WrF \ func -- Write Fonction
29772 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29778 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
29783 $02 LCD_WrF 100 20_us
29787 \ : LCD_Entry_set $04 OR LCD_WrF ;
29789 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
29791 \ : LCD_Display_Shift $10 OR LCD_WrF ;
29793 \ : LCD_Fn_Set $20 OR LCD_WrF ;
29795 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
29797 \ : LCD_Goto $80 OR LCD_WrF ;
29799 \ CODE LCD_R \ -- byte read byte from LCD
29800 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29801 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29802 \ COLON \ starts a FORTH word
29803 \ TOP_LCD 2 20_us \ -- %0000HHHH
29804 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
29805 \ HI2LO \ switch from FORTH to assembler
29806 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
29807 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
29808 \ MOV @RSP+,IP \ restore IP saved by COLON
29813 \ CODE LCD_RdS \ -- status Read Status
29814 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29819 \ CODE LCD_RdC \ -- char Read Char
29820 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29825 \ -------------+------+------+------+------++---+---+---+---+---------+
29826 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
29827 \ -------------+------+------+------+------++---+---+---+---+---------+
29828 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
29829 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
29830 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
29831 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
29832 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
29833 \ -------------+------+------+------+------++---+---+---+---+---------+
29836 \ ******************************\
29837 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29838 \ ******************************\
29839 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
29840 \ ------------------------------\
29841 \ define LPM mode for ACCEPT \
29842 \ ------------------------------\
29843 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29844 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29845 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29846 BIT.B #SW2,&SW2_IN \ test switch S2
29847 0= IF \ case of switch S2 pressed
29848 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
29850 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
29853 BIT.B #SW1,&SW1_IN \ test switch S1 input
29854 0= IF \ case of Switch S1 pressed
29855 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
29857 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
29861 RETI \ CPU is ON, GIE is OFF
29866 \ ------------------------------\
29867 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29868 \ ******************************\
29869 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29870 \ ******************************\
29871 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29872 \ \ SMclock = 8|16|24 MHz
29873 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
29874 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
29875 \ \ SR(9)=new Toggle bit memory (ADD on)
29876 \ ------------------------------\
29877 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
29878 \ ------------------------------\
29879 \ define LPM mode for ACCEPT \
29880 \ ------------------------------\
29881 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29882 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29883 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29884 \ ------------------------------\
29885 \ RC5_FirstStartBitHalfCycle: \
29886 \ ------------------------------\
29887 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
29888 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
29889 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
29890 MOV #1778,X \ RC5_Period in us
29891 MOV #14,W \ count of loop
29893 \ ------------------------------\
29894 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
29895 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
29896 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
29897 \ RC5_Compute_3/4_Period: \ |
29898 RRUM #1,X \ X=1/2 cycle |
29902 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
29903 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
29905 \ ------------------------------\
29906 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
29907 \ ------------------------------\
29908 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29909 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
29910 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29911 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29912 SUB #1,W \ decrement count loop
29913 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
29914 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29915 0<> WHILE \ ----> out of loop ----+
29916 \ RC5_compute_7/4_Time_out: \ |
29917 ADD X,Y \ | out of bound = 7/4 period
29918 \ RC5_WaitHalfCycleP1.2_IFG: \ |
29920 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
29921 0>= IF \ | if cycle time out of bound
29922 BIC #$30,&TA0CTL \ | stop timer_A0
29923 RETI \ | then quit to do nothing
29925 \ ------------------------------\ |
29926 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
29928 MOV &TA0R,X \ | | get new RC5_period value
29929 REPEAT \ ----> loop back --+ |
29930 \ ------------------------------\ |
29931 \ RC5_SampleEndOf: \ <---------------------+
29932 \ ------------------------------\
29933 BIC #$30,&TA0CTL \ stop timer_A0
29934 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
29935 \ ******************************\
29936 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29937 \ ******************************\
29938 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
29939 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
29940 XOR IP,X \ (new XOR old) Toggle bit (13)
29941 BIT #BIT13,X \ X(13) = New_RC5_command
29942 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
29944 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
29945 \ ******************************\
29946 \ RC5_ComputeNewRC5word \
29947 \ ******************************\
29949 MOV &BASE,2(PSP) \ save variable BASE before use
29950 MOV TOS,0(PSP) \ save TOS before use
29951 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
29952 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
29953 \ ******************************\
29954 \ RC5_ComputeC6bit \
29955 \ ******************************\
29956 BIT #$4000,IP \ test /C6 bit in IP
29957 0= IF BIS #$40,TOS \ set C6 bit in S
29958 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
29959 \ ******************************\
29960 \ RC5_CommandByteIsDone \ RC5_code --
29961 \ ******************************\
29963 \ ------------------------------\
29964 \ Display IR_RC5 code \
29965 \ ------------------------------\
29966 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
29967 \ ------------------------------\
29968 LO2HI \ switch from assembler to FORTH
29969 ['] LCD_CLEAR IS CR \ redirects CR
29970 ['] LCD_WrC IS EMIT \ redirects EMIT
29971 $10 BASE ! \ change BASE to hexadecimal
29972 CR ." $" 2 U.R \ print IR_RC5 code
29973 ['] (CR) IS CR \ restore CR
29974 ['] (EMIT) IS EMIT \ restore EMIT
29975 HI2LO \ switch from FORTH to assembler
29976 \ ------------------------------\
29977 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
29978 \ ------------------------------\
29979 MOV @PSP+,&BASE \ restore variable BASE
29980 RETI \ CPU is ON, GIE is OFF
29985 \ ------------------------------\
29986 \ TB0CTL = %0000 0010 1001 0100\$3C0
29987 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29988 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29989 \ -- \ID input divider \ 10 = /4
29990 \ -- \MC Mode Control \ 01 = up to TB0CCR0
29991 \ - \TBCLR TimerB Clear
29994 \ --------------------------------\\
29995 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29996 \ -- \CM Capture Mode
30001 \ --- \OUTMOD \ 011 = set/reset
30007 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
30009 \ ------------------------------\
30010 \ set TimerB to make 50kHz PWM \
30011 \ ------------------------------\
30012 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30013 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
30014 \ ------------------------------\
30015 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30016 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
30017 \ ------------------------------\
30018 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30019 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
30020 \ ------------------------------\
30021 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30022 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
30023 \ ------------------------------\
30024 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30025 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
30026 \ ------------------------------\
30027 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
30028 \ ------------------------------\
30029 \ set TimerB to generate PWM for LCD_Vo
30030 \ ------------------------------\
30031 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
30032 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
30033 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30034 \ ------------------------------\
30035 BIS.B #LCDVo,&LCDVo_DIR \
30036 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
30037 \ ------------------------------\
30038 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30039 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30040 \ ------------------------------\
30041 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30042 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30043 \ ------------------------------\
30044 \ WDT interval init part \
30045 \ ------------------------------\
30046 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
30047 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
30048 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
30049 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
30050 \ ------------------------------\
30052 \ ------------------------------\
30053 BIS.B #RC5,&IR_IE \ enable RC5_Int
30054 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30055 \ ------------------------------\
30056 \ init interrupt vectors
30057 \ ------------------------------\
30058 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
30059 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30060 \ ------------------------------\
30061 \ define LPM mode for ACCEPT \
30062 \ ------------------------------\
30063 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30064 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30065 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30067 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
30069 \ ------------------------------\
30071 \ ------------------------------\
30072 $03E8 20_US \ 1- wait 20 ms
30073 $03 TOP_LCD \ 2- send DB5=DB4=1
30074 $CD 20_US \ 3- wait 4,1 ms
30075 $03 TOP_LCD \ 4- send again DB5=DB4=1
30076 $5 20_US \ 5- wait 0,1 ms
30077 $03 TOP_LCD \ 6- send again again DB5=DB4=1
30078 $2 20_US \ wait 40 us = LCD cycle
30079 $02 TOP_LCD \ 7- send DB5=1 DB4=0
30080 $2 20_US \ wait 40 us = LCD cycle
30081 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30082 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30083 LCD_Clear \ 10- "LCD_Clear"
30084 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30085 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30086 LCD_Clear \ 10- "LCD_Clear"
30087 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30088 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30090 ['] (CR) IS CR \ ' (CR) is CR
30091 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
30093 ." RC5toLCD is running. Type STOP to quit"
30094 \ NOECHO \ uncomment to run this app without terminal connexion
30095 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
30096 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
30100 : STOP \ stops multitasking, must to be used before downloading app
30101 ['] (WARM) IS WARM \ remove START app from FORTH init process
30102 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
30110 CODE MAX \ n1 n2 -- n3 signed maximum
30111 CMP @PSP,TOS \ n2-n1
30112 S< ?GOTO FW1 \ n2<n1
30118 CODE MIN \ n1 n2 -- n3 signed minimum
30119 CMP @PSP,TOS \ n2-n1
30120 S< ?GOTO BW1 \ n2<n1
30126 : U.R \ u n -- display u unsigned in n width (n >= 2)
30128 R> OVER - 0 MAX SPACES TYPE
30132 CODE 20_US \ n -- n * 20 us
30133 BEGIN \ 3 cycles loop + 6~
30134 \ MOV #5,W \ 3 MCLK = 1 MHz
30135 \ MOV #23,W \ 3 MCLK = 4 MHz
30136 MOV #51,W \ 3 MCLK = 8 MHz
30137 \ MOV #104,W \ 3 MCLK = 16 MHz
30138 \ MOV #158,W \ 3 MCLK = 24 MHz
30139 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
30149 CODE TOP_LCD \ LCD Sample
30150 \ \ if write : %xxxxWWWW --
30151 \ \ if read : -- %0000RRRR
30152 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30153 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30154 0= IF \ write LCD bits pattern
30155 AND.B #LCD_DB,TOS \
30156 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30157 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30160 THEN \ read LCD bits pattern
30163 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30164 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30165 AND.B #LCD_DB,TOS \
30170 CODE LCD_W \ byte -- write byte to LCD
30172 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
30173 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
30174 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30175 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30176 COLON \ high level word starts here
30177 TOP_LCD 2 20_US \ write high nibble first
30182 CODE LCD_WrC \ char -- Write Char
30183 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30188 CODE LCD_WrF \ func -- Write Fonction
30189 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30195 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
30200 $02 LCD_WrF 100 20_us
30204 \ : LCD_Entry_set $04 OR LCD_WrF ;
30206 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
30208 \ : LCD_Display_Shift $10 OR LCD_WrF ;
30210 \ : LCD_Fn_Set $20 OR LCD_WrF ;
30212 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
30214 \ : LCD_Goto $80 OR LCD_WrF ;
30216 \ CODE LCD_R \ -- byte read byte from LCD
30217 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30218 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30219 \ COLON \ starts a FORTH word
30220 \ TOP_LCD 2 20_us \ -- %0000HHHH
30221 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
30222 \ HI2LO \ switch from FORTH to assembler
30223 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
30224 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
30225 \ MOV @RSP+,IP \ restore IP saved by COLON
30230 \ CODE LCD_RdS \ -- status Read Status
30231 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30236 \ CODE LCD_RdC \ -- char Read Char
30237 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30242 \ -------------+------+------+------+------++---+---+---+---+---------+
30243 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
30244 \ -------------+------+------+------+------++---+---+---+---+---------+
30245 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
30246 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
30247 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
30248 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
30249 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
30250 \ -------------+------+------+------+------++---+---+---+---+---------+
30253 \ ******************************\
30254 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30255 \ ******************************\
30256 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
30257 \ ------------------------------\
30258 \ define LPM mode for ACCEPT \
30259 \ ------------------------------\
30260 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30261 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30262 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30263 BIT.B #SW2,&SW2_IN \ test switch S2
30264 0= IF \ case of switch S2 pressed
30265 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
30267 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
30270 BIT.B #SW1,&SW1_IN \ test switch S1 input
30271 0= IF \ case of Switch S1 pressed
30272 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
30274 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
30278 RETI \ CPU is ON, GIE is OFF
30283 \ ------------------------------\
30284 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30285 \ ******************************\
30286 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30287 \ ******************************\
30288 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30289 \ \ SMclock = 8|16|24 MHz
30290 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
30291 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
30292 \ \ SR(9)=new Toggle bit memory (ADD on)
30293 \ ------------------------------\
30294 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
30295 \ ------------------------------\
30296 \ define LPM mode for ACCEPT \
30297 \ ------------------------------\
30298 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30299 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30300 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30301 \ ------------------------------\
30302 \ RC5_FirstStartBitHalfCycle: \
30303 \ ------------------------------\
30304 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
30305 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
30306 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
30307 MOV #1778,X \ RC5_Period in us
30308 MOV #14,W \ count of loop
30310 \ ------------------------------\
30311 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
30312 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
30313 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
30314 \ RC5_Compute_3/4_Period: \ |
30315 RRUM #1,X \ X=1/2 cycle |
30319 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
30320 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
30322 \ ------------------------------\
30323 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
30324 \ ------------------------------\
30325 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30326 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
30327 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30328 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30329 SUB #1,W \ decrement count loop
30330 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
30331 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30332 0<> WHILE \ ----> out of loop ----+
30333 \ RC5_compute_7/4_Time_out: \ |
30334 ADD X,Y \ | out of bound = 7/4 period
30335 \ RC5_WaitHalfCycleP1.2_IFG: \ |
30337 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
30338 0>= IF \ | if cycle time out of bound
30339 BIC #$30,&TA0CTL \ | stop timer_A0
30340 RETI \ | then quit to do nothing
30342 \ ------------------------------\ |
30343 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
30345 MOV &TA0R,X \ | | get new RC5_period value
30346 REPEAT \ ----> loop back --+ |
30347 \ ------------------------------\ |
30348 \ RC5_SampleEndOf: \ <---------------------+
30349 \ ------------------------------\
30350 BIC #$30,&TA0CTL \ stop timer_A0
30351 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
30352 \ ******************************\
30353 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30354 \ ******************************\
30355 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
30356 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
30357 XOR IP,X \ (new XOR old) Toggle bit (13)
30358 BIT #BIT13,X \ X(13) = New_RC5_command
30359 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
30361 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
30362 \ ******************************\
30363 \ RC5_ComputeNewRC5word \
30364 \ ******************************\
30366 MOV &BASE,2(PSP) \ save variable BASE before use
30367 MOV TOS,0(PSP) \ save TOS before use
30368 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
30369 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
30370 \ ******************************\
30371 \ RC5_ComputeC6bit \
30372 \ ******************************\
30373 BIT #$4000,IP \ test /C6 bit in IP
30374 0= IF BIS #$40,TOS \ set C6 bit in S
30375 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
30376 \ ******************************\
30377 \ RC5_CommandByteIsDone \ RC5_code --
30378 \ ******************************\
30380 \ ------------------------------\
30381 \ Display IR_RC5 code \
30382 \ ------------------------------\
30383 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
30384 \ ------------------------------\
30385 LO2HI \ switch from assembler to FORTH
30386 ['] LCD_CLEAR IS CR \ redirects CR
30387 ['] LCD_WrC IS EMIT \ redirects EMIT
30388 $10 BASE ! \ change BASE to hexadecimal
30389 CR ." $" 2 U.R \ print IR_RC5 code
30390 ['] (CR) IS CR \ restore CR
30391 ['] (EMIT) IS EMIT \ restore EMIT
30392 HI2LO \ switch from FORTH to assembler
30393 \ ------------------------------\
30394 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
30395 \ ------------------------------\
30396 MOV @PSP+,&BASE \ restore variable BASE
30397 RETI \ CPU is ON, GIE is OFF
30402 \ ------------------------------\
30403 \ TB0CTL = %0000 0010 1001 0100\$3C0
30404 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30405 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30406 \ -- \ID input divider \ 10 = /4
30407 \ -- \MC Mode Control \ 01 = up to TB0CCR0
30408 \ - \TBCLR TimerB Clear
30411 \ --------------------------------\\
30412 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30413 \ -- \CM Capture Mode
30418 \ --- \OUTMOD \ 011 = set/reset
30424 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
30426 \ ------------------------------\
30427 \ set TimerB to make 50kHz PWM \
30428 \ ------------------------------\
30429 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30430 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
30431 \ ------------------------------\
30432 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30433 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
30434 \ ------------------------------\
30435 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30436 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
30437 \ ------------------------------\
30438 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30439 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
30440 \ ------------------------------\
30441 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30442 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
30443 \ ------------------------------\
30444 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
30445 \ ------------------------------\
30446 \ set TimerB to generate PWM for LCD_Vo
30447 \ ------------------------------\
30448 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
30449 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
30450 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30451 \ ------------------------------\
30452 BIS.B #LCDVo,&LCDVo_DIR \
30453 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
30454 \ ------------------------------\
30455 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30456 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30457 \ ------------------------------\
30458 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30459 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30460 \ ------------------------------\
30461 \ WDT interval init part \
30462 \ ------------------------------\
30463 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
30464 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
30465 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
30466 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
30467 \ ------------------------------\
30469 \ ------------------------------\
30470 BIS.B #RC5,&IR_IE \ enable RC5_Int
30471 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30472 \ ------------------------------\
30473 \ init interrupt vectors
30474 \ ------------------------------\
30475 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
30476 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30477 \ ------------------------------\
30478 \ define LPM mode for ACCEPT \
30479 \ ------------------------------\
30480 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30481 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30482 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30484 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
30486 \ ------------------------------\
30488 \ ------------------------------\
30489 $03E8 20_US \ 1- wait 20 ms
30490 $03 TOP_LCD \ 2- send DB5=DB4=1
30491 $CD 20_US \ 3- wait 4,1 ms
30492 $03 TOP_LCD \ 4- send again DB5=DB4=1
30493 $5 20_US \ 5- wait 0,1 ms
30494 $03 TOP_LCD \ 6- send again again DB5=DB4=1
30495 $2 20_US \ wait 40 us = LCD cycle
30496 $02 TOP_LCD \ 7- send DB5=1 DB4=0
30497 $2 20_US \ wait 40 us = LCD cycle
30498 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30499 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30500 LCD_Clear \ 10- "LCD_Clear"
30501 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30502 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30503 LCD_Clear \ 10- "LCD_Clear"
30504 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30505 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30507 ['] (CR) IS CR \ ' (CR) is CR
30508 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
30510 ." RC5toLCD is running. Type STOP to quit"
30511 \ NOECHO \ uncomment to run this app without terminal connexion
30512 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
30513 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
30517 : STOP \ stops multitasking, must to be used before downloading app
30518 ['] (WARM) IS WARM \ remove START app from FORTH init process
30519 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
30527 CODE MAX \ n1 n2 -- n3 signed maximum
30528 CMP @PSP,TOS \ n2-n1
30529 S< ?GOTO FW1 \ n2<n1
30535 CODE MIN \ n1 n2 -- n3 signed minimum
30536 CMP @PSP,TOS \ n2-n1
30537 S< ?GOTO BW1 \ n2<n1
30543 : U.R \ u n -- display u unsigned in n width (n >= 2)
30545 R> OVER - 0 MAX SPACES TYPE
30549 CODE 20_US \ n -- n * 20 us
30550 BEGIN \ 3 cycles loop + 6~
30551 \ MOV #5,W \ 3 MCLK = 1 MHz
30552 \ MOV #23,W \ 3 MCLK = 4 MHz
30553 MOV #51,W \ 3 MCLK = 8 MHz
30554 \ MOV #104,W \ 3 MCLK = 16 MHz
30555 \ MOV #158,W \ 3 MCLK = 24 MHz
30556 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
30566 CODE TOP_LCD \ LCD Sample
30567 \ \ if write : %xxxxWWWW --
30568 \ \ if read : -- %0000RRRR
30569 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30570 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30571 0= IF \ write LCD bits pattern
30572 AND.B #LCD_DB,TOS \
30573 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30574 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30577 THEN \ read LCD bits pattern
30580 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30581 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30582 AND.B #LCD_DB,TOS \
30587 CODE LCD_W \ byte -- write byte to LCD
30589 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
30590 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
30591 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30592 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30593 COLON \ high level word starts here
30594 TOP_LCD 2 20_US \ write high nibble first
30599 CODE LCD_WrC \ char -- Write Char
30600 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30605 CODE LCD_WrF \ func -- Write Fonction
30606 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30612 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
30617 $02 LCD_WrF 100 20_us
30621 \ : LCD_Entry_set $04 OR LCD_WrF ;
30623 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
30625 \ : LCD_Display_Shift $10 OR LCD_WrF ;
30627 \ : LCD_Fn_Set $20 OR LCD_WrF ;
30629 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
30631 \ : LCD_Goto $80 OR LCD_WrF ;
30633 \ CODE LCD_R \ -- byte read byte from LCD
30634 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30635 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30636 \ COLON \ starts a FORTH word
30637 \ TOP_LCD 2 20_us \ -- %0000HHHH
30638 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
30639 \ HI2LO \ switch from FORTH to assembler
30640 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
30641 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
30642 \ MOV @RSP+,IP \ restore IP saved by COLON
30647 \ CODE LCD_RdS \ -- status Read Status
30648 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30653 \ CODE LCD_RdC \ -- char Read Char
30654 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30659 \ -------------+------+------+------+------++---+---+---+---+---------+
30660 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
30661 \ -------------+------+------+------+------++---+---+---+---+---------+
30662 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
30663 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
30664 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
30665 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
30666 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
30667 \ -------------+------+------+------+------++---+---+---+---+---------+
30670 \ ******************************\
30671 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30672 \ ******************************\
30673 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
30674 \ ------------------------------\
30675 \ define LPM mode for ACCEPT \
30676 \ ------------------------------\
30677 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30678 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30679 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30680 BIT.B #SW2,&SW2_IN \ test switch S2
30681 0= IF \ case of switch S2 pressed
30682 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
30684 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
30687 BIT.B #SW1,&SW1_IN \ test switch S1 input
30688 0= IF \ case of Switch S1 pressed
30689 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
30691 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
30695 RETI \ CPU is ON, GIE is OFF
30700 \ ------------------------------\
30701 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30702 \ ******************************\
30703 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30704 \ ******************************\
30705 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30706 \ \ SMclock = 8|16|24 MHz
30707 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
30708 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
30709 \ \ SR(9)=new Toggle bit memory (ADD on)
30710 \ ------------------------------\
30711 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
30712 \ ------------------------------\
30713 \ define LPM mode for ACCEPT \
30714 \ ------------------------------\
30715 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30716 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30717 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30718 \ ------------------------------\
30719 \ RC5_FirstStartBitHalfCycle: \
30720 \ ------------------------------\
30721 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
30722 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
30723 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
30724 MOV #1778,X \ RC5_Period in us
30725 MOV #14,W \ count of loop
30727 \ ------------------------------\
30728 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
30729 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
30730 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
30731 \ RC5_Compute_3/4_Period: \ |
30732 RRUM #1,X \ X=1/2 cycle |
30736 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
30737 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
30739 \ ------------------------------\
30740 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
30741 \ ------------------------------\
30742 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30743 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
30744 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30745 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30746 SUB #1,W \ decrement count loop
30747 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
30748 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30749 0<> WHILE \ ----> out of loop ----+
30750 \ RC5_compute_7/4_Time_out: \ |
30751 ADD X,Y \ | out of bound = 7/4 period
30752 \ RC5_WaitHalfCycleP1.2_IFG: \ |
30754 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
30755 0>= IF \ | if cycle time out of bound
30756 BIC #$30,&TA0CTL \ | stop timer_A0
30757 RETI \ | then quit to do nothing
30759 \ ------------------------------\ |
30760 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
30762 MOV &TA0R,X \ | | get new RC5_period value
30763 REPEAT \ ----> loop back --+ |
30764 \ ------------------------------\ |
30765 \ RC5_SampleEndOf: \ <---------------------+
30766 \ ------------------------------\
30767 BIC #$30,&TA0CTL \ stop timer_A0
30768 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
30769 \ ******************************\
30770 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30771 \ ******************************\
30772 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
30773 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
30774 XOR IP,X \ (new XOR old) Toggle bit (13)
30775 BIT #BIT13,X \ X(13) = New_RC5_command
30776 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
30778 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
30779 \ ******************************\
30780 \ RC5_ComputeNewRC5word \
30781 \ ******************************\
30783 MOV &BASE,2(PSP) \ save variable BASE before use
30784 MOV TOS,0(PSP) \ save TOS before use
30785 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
30786 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
30787 \ ******************************\
30788 \ RC5_ComputeC6bit \
30789 \ ******************************\
30790 BIT #$4000,IP \ test /C6 bit in IP
30791 0= IF BIS #$40,TOS \ set C6 bit in S
30792 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
30793 \ ******************************\
30794 \ RC5_CommandByteIsDone \ RC5_code --
30795 \ ******************************\
30797 \ ------------------------------\
30798 \ Display IR_RC5 code \
30799 \ ------------------------------\
30800 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
30801 \ ------------------------------\
30802 LO2HI \ switch from assembler to FORTH
30803 ['] LCD_CLEAR IS CR \ redirects CR
30804 ['] LCD_WrC IS EMIT \ redirects EMIT
30805 $10 BASE ! \ change BASE to hexadecimal
30806 CR ." $" 2 U.R \ print IR_RC5 code
30807 ['] (CR) IS CR \ restore CR
30808 ['] (EMIT) IS EMIT \ restore EMIT
30809 HI2LO \ switch from FORTH to assembler
30810 \ ------------------------------\
30811 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
30812 \ ------------------------------\
30813 MOV @PSP+,&BASE \ restore variable BASE
30814 RETI \ CPU is ON, GIE is OFF
30819 \ ------------------------------\
30820 \ TB0CTL = %0000 0010 1001 0100\$3C0
30821 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30822 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30823 \ -- \ID input divider \ 10 = /4
30824 \ -- \MC Mode Control \ 01 = up to TB0CCR0
30825 \ - \TBCLR TimerB Clear
30828 \ --------------------------------\\
30829 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30830 \ -- \CM Capture Mode
30835 \ --- \OUTMOD \ 011 = set/reset
30841 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
30843 \ ------------------------------\
30844 \ set TimerB to make 50kHz PWM \
30845 \ ------------------------------\
30846 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30847 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
30848 \ ------------------------------\
30849 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
30850 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
30851 \ ------------------------------\
30852 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30853 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
30854 \ ------------------------------\
30855 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30856 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
30857 \ ------------------------------\
30858 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
30859 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
30860 \ ------------------------------\
30861 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
30862 \ ------------------------------\
30863 \ set TimerB to generate PWM for LCD_Vo
30864 \ ------------------------------\
30865 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
30866 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
30867 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30868 \ ------------------------------\
30869 BIS.B #LCDVo,&LCDVo_DIR \
30870 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
30871 \ ------------------------------\
30872 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30873 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30874 \ ------------------------------\
30875 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30876 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30877 \ ------------------------------\
30878 \ WDT interval init part \
30879 \ ------------------------------\
30880 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
30881 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
30882 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
30883 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
30884 \ ------------------------------\
30886 \ ------------------------------\
30887 BIS.B #RC5,&IR_IE \ enable RC5_Int
30888 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30889 \ ------------------------------\
30890 \ init interrupt vectors
30891 \ ------------------------------\
30892 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
30893 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30894 \ ------------------------------\
30895 \ define LPM mode for ACCEPT \
30896 \ ------------------------------\
30897 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30898 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30899 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30901 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
30903 \ ------------------------------\
30905 \ ------------------------------\
30906 $03E8 20_US \ 1- wait 20 ms
30907 $03 TOP_LCD \ 2- send DB5=DB4=1
30908 $CD 20_US \ 3- wait 4,1 ms
30909 $03 TOP_LCD \ 4- send again DB5=DB4=1
30910 $5 20_US \ 5- wait 0,1 ms
30911 $03 TOP_LCD \ 6- send again again DB5=DB4=1
30912 $2 20_US \ wait 40 us = LCD cycle
30913 $02 TOP_LCD \ 7- send DB5=1 DB4=0
30914 $2 20_US \ wait 40 us = LCD cycle
30915 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30916 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30917 LCD_Clear \ 10- "LCD_Clear"
30918 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30919 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30920 LCD_Clear \ 10- "LCD_Clear"
30921 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30922 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30924 ['] (CR) IS CR \ ' (CR) is CR
30925 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
30927 ." RC5toLCD is running. Type STOP to quit"
30928 \ NOECHO \ uncomment to run this app without terminal connexion
30929 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
30930 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
30934 : STOP \ stops multitasking, must to be used before downloading app
30935 ['] (WARM) IS WARM \ remove START app from FORTH init process
30936 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
30944 CODE MAX \ n1 n2 -- n3 signed maximum
30945 CMP @PSP,TOS \ n2-n1
30946 S< ?GOTO FW1 \ n2<n1
30952 CODE MIN \ n1 n2 -- n3 signed minimum
30953 CMP @PSP,TOS \ n2-n1
30954 S< ?GOTO BW1 \ n2<n1
30960 : U.R \ u n -- display u unsigned in n width (n >= 2)
30962 R> OVER - 0 MAX SPACES TYPE
30966 CODE 20_US \ n -- n * 20 us
30967 BEGIN \ 3 cycles loop + 6~
30968 \ MOV #5,W \ 3 MCLK = 1 MHz
30969 \ MOV #23,W \ 3 MCLK = 4 MHz
30970 MOV #51,W \ 3 MCLK = 8 MHz
30971 \ MOV #104,W \ 3 MCLK = 16 MHz
30972 \ MOV #158,W \ 3 MCLK = 24 MHz
30973 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
30983 CODE TOP_LCD \ LCD Sample
30984 \ \ if write : %xxxxWWWW --
30985 \ \ if read : -- %0000RRRR
30986 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30987 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30988 0= IF \ write LCD bits pattern
30989 AND.B #LCD_DB,TOS \
30990 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30991 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30994 THEN \ read LCD bits pattern
30997 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30998 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30999 AND.B #LCD_DB,TOS \
31004 CODE LCD_W \ byte -- write byte to LCD
31006 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31007 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31008 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31009 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31010 COLON \ high level word starts here
31011 TOP_LCD 2 20_US \ write high nibble first
31016 CODE LCD_WrC \ char -- Write Char
31017 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31022 CODE LCD_WrF \ func -- Write Fonction
31023 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31029 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
31034 $02 LCD_WrF 100 20_us
31038 \ : LCD_Entry_set $04 OR LCD_WrF ;
31040 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
31042 \ : LCD_Display_Shift $10 OR LCD_WrF ;
31044 \ : LCD_Fn_Set $20 OR LCD_WrF ;
31046 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
31048 \ : LCD_Goto $80 OR LCD_WrF ;
31050 \ CODE LCD_R \ -- byte read byte from LCD
31051 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31052 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31053 \ COLON \ starts a FORTH word
31054 \ TOP_LCD 2 20_us \ -- %0000HHHH
31055 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31056 \ HI2LO \ switch from FORTH to assembler
31057 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31058 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31059 \ MOV @RSP+,IP \ restore IP saved by COLON
31064 \ CODE LCD_RdS \ -- status Read Status
31065 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31070 \ CODE LCD_RdC \ -- char Read Char
31071 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31076 \ -------------+------+------+------+------++---+---+---+---+---------+
31077 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
31078 \ -------------+------+------+------+------++---+---+---+---+---------+
31079 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
31080 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
31081 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
31082 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
31083 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
31084 \ -------------+------+------+------+------++---+---+---+---+---------+
31087 \ ******************************\
31088 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31089 \ ******************************\
31090 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
31091 \ ------------------------------\
31092 \ define LPM mode for ACCEPT \
31093 \ ------------------------------\
31094 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31095 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31096 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31097 BIT.B #SW2,&SW2_IN \ test switch S2
31098 0= IF \ case of switch S2 pressed
31099 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
31101 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
31104 BIT.B #SW1,&SW1_IN \ test switch S1 input
31105 0= IF \ case of Switch S1 pressed
31106 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
31108 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
31112 RETI \ CPU is ON, GIE is OFF
31117 \ ------------------------------\
31118 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31119 \ ******************************\
31120 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31121 \ ******************************\
31122 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31123 \ \ SMclock = 8|16|24 MHz
31124 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
31125 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
31126 \ \ SR(9)=new Toggle bit memory (ADD on)
31127 \ ------------------------------\
31128 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
31129 \ ------------------------------\
31130 \ define LPM mode for ACCEPT \
31131 \ ------------------------------\
31132 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31133 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31134 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31135 \ ------------------------------\
31136 \ RC5_FirstStartBitHalfCycle: \
31137 \ ------------------------------\
31138 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
31139 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
31140 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
31141 MOV #1778,X \ RC5_Period in us
31142 MOV #14,W \ count of loop
31144 \ ------------------------------\
31145 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
31146 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
31147 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
31148 \ RC5_Compute_3/4_Period: \ |
31149 RRUM #1,X \ X=1/2 cycle |
31153 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
31154 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
31156 \ ------------------------------\
31157 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
31158 \ ------------------------------\
31159 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31160 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
31161 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31162 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31163 SUB #1,W \ decrement count loop
31164 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
31165 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31166 0<> WHILE \ ----> out of loop ----+
31167 \ RC5_compute_7/4_Time_out: \ |
31168 ADD X,Y \ | out of bound = 7/4 period
31169 \ RC5_WaitHalfCycleP1.2_IFG: \ |
31171 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
31172 0>= IF \ | if cycle time out of bound
31173 BIC #$30,&TA0CTL \ | stop timer_A0
31174 RETI \ | then quit to do nothing
31176 \ ------------------------------\ |
31177 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
31179 MOV &TA0R,X \ | | get new RC5_period value
31180 REPEAT \ ----> loop back --+ |
31181 \ ------------------------------\ |
31182 \ RC5_SampleEndOf: \ <---------------------+
31183 \ ------------------------------\
31184 BIC #$30,&TA0CTL \ stop timer_A0
31185 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
31186 \ ******************************\
31187 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31188 \ ******************************\
31189 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
31190 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
31191 XOR IP,X \ (new XOR old) Toggle bit (13)
31192 BIT #BIT13,X \ X(13) = New_RC5_command
31193 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
31195 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
31196 \ ******************************\
31197 \ RC5_ComputeNewRC5word \
31198 \ ******************************\
31200 MOV &BASE,2(PSP) \ save variable BASE before use
31201 MOV TOS,0(PSP) \ save TOS before use
31202 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
31203 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
31204 \ ******************************\
31205 \ RC5_ComputeC6bit \
31206 \ ******************************\
31207 BIT #$4000,IP \ test /C6 bit in IP
31208 0= IF BIS #$40,TOS \ set C6 bit in S
31209 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
31210 \ ******************************\
31211 \ RC5_CommandByteIsDone \ RC5_code --
31212 \ ******************************\
31214 \ ------------------------------\
31215 \ Display IR_RC5 code \
31216 \ ------------------------------\
31217 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
31218 \ ------------------------------\
31219 LO2HI \ switch from assembler to FORTH
31220 ['] LCD_CLEAR IS CR \ redirects CR
31221 ['] LCD_WrC IS EMIT \ redirects EMIT
31222 $10 BASE ! \ change BASE to hexadecimal
31223 CR ." $" 2 U.R \ print IR_RC5 code
31224 ['] (CR) IS CR \ restore CR
31225 ['] (EMIT) IS EMIT \ restore EMIT
31226 HI2LO \ switch from FORTH to assembler
31227 \ ------------------------------\
31228 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
31229 \ ------------------------------\
31230 MOV @PSP+,&BASE \ restore variable BASE
31231 RETI \ CPU is ON, GIE is OFF
31236 \ ------------------------------\
31237 \ TB0CTL = %0000 0010 1001 0100\$3C0
31238 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31239 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31240 \ -- \ID input divider \ 10 = /4
31241 \ -- \MC Mode Control \ 01 = up to TB0CCR0
31242 \ - \TBCLR TimerB Clear
31245 \ --------------------------------\\
31246 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31247 \ -- \CM Capture Mode
31252 \ --- \OUTMOD \ 011 = set/reset
31258 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
31260 \ ------------------------------\
31261 \ set TimerB to make 50kHz PWM \
31262 \ ------------------------------\
31263 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31264 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
31265 \ ------------------------------\
31266 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31267 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
31268 \ ------------------------------\
31269 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31270 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
31271 \ ------------------------------\
31272 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31273 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
31274 \ ------------------------------\
31275 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31276 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
31277 \ ------------------------------\
31278 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
31279 \ ------------------------------\
31280 \ set TimerB to generate PWM for LCD_Vo
31281 \ ------------------------------\
31282 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
31283 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
31284 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31285 \ ------------------------------\
31286 BIS.B #LCDVo,&LCDVo_DIR \
31287 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
31288 \ ------------------------------\
31289 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31290 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31291 \ ------------------------------\
31292 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31293 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31294 \ ------------------------------\
31295 \ WDT interval init part \
31296 \ ------------------------------\
31297 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
31298 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
31299 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
31300 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
31301 \ ------------------------------\
31303 \ ------------------------------\
31304 BIS.B #RC5,&IR_IE \ enable RC5_Int
31305 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31306 \ ------------------------------\
31307 \ init interrupt vectors
31308 \ ------------------------------\
31309 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
31310 MOV #RC5_INT,&IR_Vec \ init interrupt vector
31311 \ ------------------------------\
31312 \ define LPM mode for ACCEPT \
31313 \ ------------------------------\
31314 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31315 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31316 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31318 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
31320 \ ------------------------------\
31322 \ ------------------------------\
31323 $03E8 20_US \ 1- wait 20 ms
31324 $03 TOP_LCD \ 2- send DB5=DB4=1
31325 $CD 20_US \ 3- wait 4,1 ms
31326 $03 TOP_LCD \ 4- send again DB5=DB4=1
31327 $5 20_US \ 5- wait 0,1 ms
31328 $03 TOP_LCD \ 6- send again again DB5=DB4=1
31329 $2 20_US \ wait 40 us = LCD cycle
31330 $02 TOP_LCD \ 7- send DB5=1 DB4=0
31331 $2 20_US \ wait 40 us = LCD cycle
31332 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31333 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31334 LCD_Clear \ 10- "LCD_Clear"
31335 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31336 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31337 LCD_Clear \ 10- "LCD_Clear"
31338 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31339 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31341 ['] (CR) IS CR \ ' (CR) is CR
31342 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
31344 ." RC5toLCD is running. Type STOP to quit"
31345 \ NOECHO \ uncomment to run this app without terminal connexion
31346 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
31347 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
31351 : STOP \ stops multitasking, must to be used before downloading app
31352 ['] (WARM) IS WARM \ remove START app from FORTH init process
31353 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
31361 CODE MAX \ n1 n2 -- n3 signed maximum
31362 CMP @PSP,TOS \ n2-n1
31363 S< ?GOTO FW1 \ n2<n1
31369 CODE MIN \ n1 n2 -- n3 signed minimum
31370 CMP @PSP,TOS \ n2-n1
31371 S< ?GOTO BW1 \ n2<n1
31377 : U.R \ u n -- display u unsigned in n width (n >= 2)
31379 R> OVER - 0 MAX SPACES TYPE
31383 CODE 20_US \ n -- n * 20 us
31384 BEGIN \ 3 cycles loop + 6~
31385 \ MOV #5,W \ 3 MCLK = 1 MHz
31386 \ MOV #23,W \ 3 MCLK = 4 MHz
31387 MOV #51,W \ 3 MCLK = 8 MHz
31388 \ MOV #104,W \ 3 MCLK = 16 MHz
31389 \ MOV #158,W \ 3 MCLK = 24 MHz
31390 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
31400 CODE TOP_LCD \ LCD Sample
31401 \ \ if write : %xxxxWWWW --
31402 \ \ if read : -- %0000RRRR
31403 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31404 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31405 0= IF \ write LCD bits pattern
31406 AND.B #LCD_DB,TOS \
31407 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31408 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31411 THEN \ read LCD bits pattern
31414 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31415 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31416 AND.B #LCD_DB,TOS \
31421 CODE LCD_W \ byte -- write byte to LCD
31423 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31424 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31425 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31426 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31427 COLON \ high level word starts here
31428 TOP_LCD 2 20_US \ write high nibble first
31433 CODE LCD_WrC \ char -- Write Char
31434 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31439 CODE LCD_WrF \ func -- Write Fonction
31440 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31446 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
31451 $02 LCD_WrF 100 20_us
31455 \ : LCD_Entry_set $04 OR LCD_WrF ;
31457 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
31459 \ : LCD_Display_Shift $10 OR LCD_WrF ;
31461 \ : LCD_Fn_Set $20 OR LCD_WrF ;
31463 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
31465 \ : LCD_Goto $80 OR LCD_WrF ;
31467 \ CODE LCD_R \ -- byte read byte from LCD
31468 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31469 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31470 \ COLON \ starts a FORTH word
31471 \ TOP_LCD 2 20_us \ -- %0000HHHH
31472 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31473 \ HI2LO \ switch from FORTH to assembler
31474 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31475 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31476 \ MOV @RSP+,IP \ restore IP saved by COLON
31481 \ CODE LCD_RdS \ -- status Read Status
31482 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31487 \ CODE LCD_RdC \ -- char Read Char
31488 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31493 \ -------------+------+------+------+------++---+---+---+---+---------+
31494 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
31495 \ -------------+------+------+------+------++---+---+---+---+---------+
31496 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
31497 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
31498 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
31499 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
31500 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
31501 \ -------------+------+------+------+------++---+---+---+---+---------+
31504 \ ******************************\
31505 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31506 \ ******************************\
31507 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
31508 \ ------------------------------\
31509 \ define LPM mode for ACCEPT \
31510 \ ------------------------------\
31511 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31512 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31513 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31514 BIT.B #SW2,&SW2_IN \ test switch S2
31515 0= IF \ case of switch S2 pressed
31516 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
31518 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
31521 BIT.B #SW1,&SW1_IN \ test switch S1 input
31522 0= IF \ case of Switch S1 pressed
31523 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
31525 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
31529 RETI \ CPU is ON, GIE is OFF
31534 \ ------------------------------\
31535 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31536 \ ******************************\
31537 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31538 \ ******************************\
31539 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31540 \ \ SMclock = 8|16|24 MHz
31541 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
31542 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
31543 \ \ SR(9)=new Toggle bit memory (ADD on)
31544 \ ------------------------------\
31545 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
31546 \ ------------------------------\
31547 \ define LPM mode for ACCEPT \
31548 \ ------------------------------\
31549 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31550 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31551 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31552 \ ------------------------------\
31553 \ RC5_FirstStartBitHalfCycle: \
31554 \ ------------------------------\
31555 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
31556 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
31557 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
31558 MOV #1778,X \ RC5_Period in us
31559 MOV #14,W \ count of loop
31561 \ ------------------------------\
31562 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
31563 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
31564 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
31565 \ RC5_Compute_3/4_Period: \ |
31566 RRUM #1,X \ X=1/2 cycle |
31570 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
31571 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
31573 \ ------------------------------\
31574 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
31575 \ ------------------------------\
31576 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31577 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
31578 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31579 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31580 SUB #1,W \ decrement count loop
31581 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
31582 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31583 0<> WHILE \ ----> out of loop ----+
31584 \ RC5_compute_7/4_Time_out: \ |
31585 ADD X,Y \ | out of bound = 7/4 period
31586 \ RC5_WaitHalfCycleP1.2_IFG: \ |
31588 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
31589 0>= IF \ | if cycle time out of bound
31590 BIC #$30,&TA0CTL \ | stop timer_A0
31591 RETI \ | then quit to do nothing
31593 \ ------------------------------\ |
31594 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
31596 MOV &TA0R,X \ | | get new RC5_period value
31597 REPEAT \ ----> loop back --+ |
31598 \ ------------------------------\ |
31599 \ RC5_SampleEndOf: \ <---------------------+
31600 \ ------------------------------\
31601 BIC #$30,&TA0CTL \ stop timer_A0
31602 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
31603 \ ******************************\
31604 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31605 \ ******************************\
31606 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
31607 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
31608 XOR IP,X \ (new XOR old) Toggle bit (13)
31609 BIT #BIT13,X \ X(13) = New_RC5_command
31610 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
31612 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
31613 \ ******************************\
31614 \ RC5_ComputeNewRC5word \
31615 \ ******************************\
31617 MOV &BASE,2(PSP) \ save variable BASE before use
31618 MOV TOS,0(PSP) \ save TOS before use
31619 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
31620 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
31621 \ ******************************\
31622 \ RC5_ComputeC6bit \
31623 \ ******************************\
31624 BIT #$4000,IP \ test /C6 bit in IP
31625 0= IF BIS #$40,TOS \ set C6 bit in S
31626 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
31627 \ ******************************\
31628 \ RC5_CommandByteIsDone \ RC5_code --
31629 \ ******************************\
31631 \ ------------------------------\
31632 \ Display IR_RC5 code \
31633 \ ------------------------------\
31634 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
31635 \ ------------------------------\
31636 LO2HI \ switch from assembler to FORTH
31637 ['] LCD_CLEAR IS CR \ redirects CR
31638 ['] LCD_WrC IS EMIT \ redirects EMIT
31639 $10 BASE ! \ change BASE to hexadecimal
31640 CR ." $" 2 U.R \ print IR_RC5 code
31641 ['] (CR) IS CR \ restore CR
31642 ['] (EMIT) IS EMIT \ restore EMIT
31643 HI2LO \ switch from FORTH to assembler
31644 \ ------------------------------\
31645 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
31646 \ ------------------------------\
31647 MOV @PSP+,&BASE \ restore variable BASE
31648 RETI \ CPU is ON, GIE is OFF
31653 \ ------------------------------\
31654 \ TB0CTL = %0000 0010 1001 0100\$3C0
31655 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31656 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31657 \ -- \ID input divider \ 10 = /4
31658 \ -- \MC Mode Control \ 01 = up to TB0CCR0
31659 \ - \TBCLR TimerB Clear
31662 \ --------------------------------\\
31663 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31664 \ -- \CM Capture Mode
31669 \ --- \OUTMOD \ 011 = set/reset
31675 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
31677 \ ------------------------------\
31678 \ set TimerB to make 50kHz PWM \
31679 \ ------------------------------\
31680 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31681 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
31682 \ ------------------------------\
31683 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
31684 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
31685 \ ------------------------------\
31686 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31687 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
31688 \ ------------------------------\
31689 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31690 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
31691 \ ------------------------------\
31692 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
31693 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
31694 \ ------------------------------\
31695 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
31696 \ ------------------------------\
31697 \ set TimerB to generate PWM for LCD_Vo
31698 \ ------------------------------\
31699 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
31700 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
31701 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31702 \ ------------------------------\
31703 BIS.B #LCDVo,&LCDVo_DIR \
31704 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
31705 \ ------------------------------\
31706 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31707 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31708 \ ------------------------------\
31709 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31710 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31711 \ ------------------------------\
31712 \ WDT interval init part \
31713 \ ------------------------------\
31714 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
31715 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
31716 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
31717 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
31718 \ ------------------------------\
31720 \ ------------------------------\
31721 BIS.B #RC5,&IR_IE \ enable RC5_Int
31722 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31723 \ ------------------------------\
31724 \ init interrupt vectors
31725 \ ------------------------------\
31726 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
31727 MOV #RC5_INT,&IR_Vec \ init interrupt vector
31728 \ ------------------------------\
31729 \ define LPM mode for ACCEPT \
31730 \ ------------------------------\
31731 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31732 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31733 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31735 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
31737 \ ------------------------------\
31739 \ ------------------------------\
31740 $03E8 20_US \ 1- wait 20 ms
31741 $03 TOP_LCD \ 2- send DB5=DB4=1
31742 $CD 20_US \ 3- wait 4,1 ms
31743 $03 TOP_LCD \ 4- send again DB5=DB4=1
31744 $5 20_US \ 5- wait 0,1 ms
31745 $03 TOP_LCD \ 6- send again again DB5=DB4=1
31746 $2 20_US \ wait 40 us = LCD cycle
31747 $02 TOP_LCD \ 7- send DB5=1 DB4=0
31748 $2 20_US \ wait 40 us = LCD cycle
31749 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31750 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31751 LCD_Clear \ 10- "LCD_Clear"
31752 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31753 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31754 LCD_Clear \ 10- "LCD_Clear"
31755 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31756 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31758 ['] (CR) IS CR \ ' (CR) is CR
31759 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
31761 ." RC5toLCD is running. Type STOP to quit"
31762 \ NOECHO \ uncomment to run this app without terminal connexion
31763 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
31764 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
31768 : STOP \ stops multitasking, must to be used before downloading app
31769 ['] (WARM) IS WARM \ remove START app from FORTH init process
31770 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
31778 CODE MAX \ n1 n2 -- n3 signed maximum
31779 CMP @PSP,TOS \ n2-n1
31780 S< ?GOTO FW1 \ n2<n1
31786 CODE MIN \ n1 n2 -- n3 signed minimum
31787 CMP @PSP,TOS \ n2-n1
31788 S< ?GOTO BW1 \ n2<n1
31794 : U.R \ u n -- display u unsigned in n width (n >= 2)
31796 R> OVER - 0 MAX SPACES TYPE
31800 CODE 20_US \ n -- n * 20 us
31801 BEGIN \ 3 cycles loop + 6~
31802 \ MOV #5,W \ 3 MCLK = 1 MHz
31803 \ MOV #23,W \ 3 MCLK = 4 MHz
31804 MOV #51,W \ 3 MCLK = 8 MHz
31805 \ MOV #104,W \ 3 MCLK = 16 MHz
31806 \ MOV #158,W \ 3 MCLK = 24 MHz
31807 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
31817 CODE TOP_LCD \ LCD Sample
31818 \ \ if write : %xxxxWWWW --
31819 \ \ if read : -- %0000RRRR
31820 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31821 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31822 0= IF \ write LCD bits pattern
31823 AND.B #LCD_DB,TOS \
31824 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31825 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31828 THEN \ read LCD bits pattern
31831 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31832 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31833 AND.B #LCD_DB,TOS \
31838 CODE LCD_W \ byte -- write byte to LCD
31840 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
31841 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
31842 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31843 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31844 COLON \ high level word starts here
31845 TOP_LCD 2 20_US \ write high nibble first
31850 CODE LCD_WrC \ char -- Write Char
31851 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31856 CODE LCD_WrF \ func -- Write Fonction
31857 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31863 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
31868 $02 LCD_WrF 100 20_us
31872 \ : LCD_Entry_set $04 OR LCD_WrF ;
31874 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
31876 \ : LCD_Display_Shift $10 OR LCD_WrF ;
31878 \ : LCD_Fn_Set $20 OR LCD_WrF ;
31880 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
31882 \ : LCD_Goto $80 OR LCD_WrF ;
31884 \ CODE LCD_R \ -- byte read byte from LCD
31885 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31886 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31887 \ COLON \ starts a FORTH word
31888 \ TOP_LCD 2 20_us \ -- %0000HHHH
31889 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
31890 \ HI2LO \ switch from FORTH to assembler
31891 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
31892 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
31893 \ MOV @RSP+,IP \ restore IP saved by COLON
31898 \ CODE LCD_RdS \ -- status Read Status
31899 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31904 \ CODE LCD_RdC \ -- char Read Char
31905 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31910 \ -------------+------+------+------+------++---+---+---+---+---------+
31911 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
31912 \ -------------+------+------+------+------++---+---+---+---+---------+
31913 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
31914 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
31915 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
31916 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
31917 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
31918 \ -------------+------+------+------+------++---+---+---+---+---------+
31921 \ ******************************\
31922 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31923 \ ******************************\
31924 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
31925 \ ------------------------------\
31926 \ define LPM mode for ACCEPT \
31927 \ ------------------------------\
31928 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31929 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31930 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31931 BIT.B #SW2,&SW2_IN \ test switch S2
31932 0= IF \ case of switch S2 pressed
31933 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
31935 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
31938 BIT.B #SW1,&SW1_IN \ test switch S1 input
31939 0= IF \ case of Switch S1 pressed
31940 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
31942 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
31946 RETI \ CPU is ON, GIE is OFF
31951 \ ------------------------------\
31952 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31953 \ ******************************\
31954 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31955 \ ******************************\
31956 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31957 \ \ SMclock = 8|16|24 MHz
31958 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
31959 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
31960 \ \ SR(9)=new Toggle bit memory (ADD on)
31961 \ ------------------------------\
31962 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
31963 \ ------------------------------\
31964 \ define LPM mode for ACCEPT \
31965 \ ------------------------------\
31966 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31967 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31968 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31969 \ ------------------------------\
31970 \ RC5_FirstStartBitHalfCycle: \
31971 \ ------------------------------\
31972 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
31973 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
31974 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
31975 MOV #1778,X \ RC5_Period in us
31976 MOV #14,W \ count of loop
31978 \ ------------------------------\
31979 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
31980 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
31981 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
31982 \ RC5_Compute_3/4_Period: \ |
31983 RRUM #1,X \ X=1/2 cycle |
31987 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
31988 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
31990 \ ------------------------------\
31991 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
31992 \ ------------------------------\
31993 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31994 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
31995 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31996 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31997 SUB #1,W \ decrement count loop
31998 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
31999 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32000 0<> WHILE \ ----> out of loop ----+
32001 \ RC5_compute_7/4_Time_out: \ |
32002 ADD X,Y \ | out of bound = 7/4 period
32003 \ RC5_WaitHalfCycleP1.2_IFG: \ |
32005 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
32006 0>= IF \ | if cycle time out of bound
32007 BIC #$30,&TA0CTL \ | stop timer_A0
32008 RETI \ | then quit to do nothing
32010 \ ------------------------------\ |
32011 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
32013 MOV &TA0R,X \ | | get new RC5_period value
32014 REPEAT \ ----> loop back --+ |
32015 \ ------------------------------\ |
32016 \ RC5_SampleEndOf: \ <---------------------+
32017 \ ------------------------------\
32018 BIC #$30,&TA0CTL \ stop timer_A0
32019 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
32020 \ ******************************\
32021 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32022 \ ******************************\
32023 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
32024 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
32025 XOR IP,X \ (new XOR old) Toggle bit (13)
32026 BIT #BIT13,X \ X(13) = New_RC5_command
32027 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
32029 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
32030 \ ******************************\
32031 \ RC5_ComputeNewRC5word \
32032 \ ******************************\
32034 MOV &BASE,2(PSP) \ save variable BASE before use
32035 MOV TOS,0(PSP) \ save TOS before use
32036 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
32037 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
32038 \ ******************************\
32039 \ RC5_ComputeC6bit \
32040 \ ******************************\
32041 BIT #$4000,IP \ test /C6 bit in IP
32042 0= IF BIS #$40,TOS \ set C6 bit in S
32043 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
32044 \ ******************************\
32045 \ RC5_CommandByteIsDone \ RC5_code --
32046 \ ******************************\
32048 \ ------------------------------\
32049 \ Display IR_RC5 code \
32050 \ ------------------------------\
32051 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
32052 \ ------------------------------\
32053 LO2HI \ switch from assembler to FORTH
32054 ['] LCD_CLEAR IS CR \ redirects CR
32055 ['] LCD_WrC IS EMIT \ redirects EMIT
32056 $10 BASE ! \ change BASE to hexadecimal
32057 CR ." $" 2 U.R \ print IR_RC5 code
32058 ['] (CR) IS CR \ restore CR
32059 ['] (EMIT) IS EMIT \ restore EMIT
32060 HI2LO \ switch from FORTH to assembler
32061 \ ------------------------------\
32062 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
32063 \ ------------------------------\
32064 MOV @PSP+,&BASE \ restore variable BASE
32065 RETI \ CPU is ON, GIE is OFF
32070 \ ------------------------------\
32071 \ TB0CTL = %0000 0010 1001 0100\$3C0
32072 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32073 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32074 \ -- \ID input divider \ 10 = /4
32075 \ -- \MC Mode Control \ 01 = up to TB0CCR0
32076 \ - \TBCLR TimerB Clear
32079 \ --------------------------------\\
32080 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32081 \ -- \CM Capture Mode
32086 \ --- \OUTMOD \ 011 = set/reset
32092 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
32094 \ ------------------------------\
32095 \ set TimerB to make 50kHz PWM \
32096 \ ------------------------------\
32097 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32098 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
32099 \ ------------------------------\
32100 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32101 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
32102 \ ------------------------------\
32103 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32104 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
32105 \ ------------------------------\
32106 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32107 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
32108 \ ------------------------------\
32109 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32110 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
32111 \ ------------------------------\
32112 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
32113 \ ------------------------------\
32114 \ set TimerB to generate PWM for LCD_Vo
32115 \ ------------------------------\
32116 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
32117 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
32118 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32119 \ ------------------------------\
32120 BIS.B #LCDVo,&LCDVo_DIR \
32121 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
32122 \ ------------------------------\
32123 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32124 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32125 \ ------------------------------\
32126 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32127 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32128 \ ------------------------------\
32129 \ WDT interval init part \
32130 \ ------------------------------\
32131 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
32132 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
32133 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
32134 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
32135 \ ------------------------------\
32137 \ ------------------------------\
32138 BIS.B #RC5,&IR_IE \ enable RC5_Int
32139 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32140 \ ------------------------------\
32141 \ init interrupt vectors
32142 \ ------------------------------\
32143 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
32144 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32145 \ ------------------------------\
32146 \ define LPM mode for ACCEPT \
32147 \ ------------------------------\
32148 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32149 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32150 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32152 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
32154 \ ------------------------------\
32156 \ ------------------------------\
32157 $03E8 20_US \ 1- wait 20 ms
32158 $03 TOP_LCD \ 2- send DB5=DB4=1
32159 $CD 20_US \ 3- wait 4,1 ms
32160 $03 TOP_LCD \ 4- send again DB5=DB4=1
32161 $5 20_US \ 5- wait 0,1 ms
32162 $03 TOP_LCD \ 6- send again again DB5=DB4=1
32163 $2 20_US \ wait 40 us = LCD cycle
32164 $02 TOP_LCD \ 7- send DB5=1 DB4=0
32165 $2 20_US \ wait 40 us = LCD cycle
32166 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32167 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32168 LCD_Clear \ 10- "LCD_Clear"
32169 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32170 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32171 LCD_Clear \ 10- "LCD_Clear"
32172 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32173 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32175 ['] (CR) IS CR \ ' (CR) is CR
32176 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
32178 ." RC5toLCD is running. Type STOP to quit"
32179 \ NOECHO \ uncomment to run this app without terminal connexion
32180 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
32181 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
32185 : STOP \ stops multitasking, must to be used before downloading app
32186 ['] (WARM) IS WARM \ remove START app from FORTH init process
32187 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
32195 CODE MAX \ n1 n2 -- n3 signed maximum
32196 CMP @PSP,TOS \ n2-n1
32197 S< ?GOTO FW1 \ n2<n1
32203 CODE MIN \ n1 n2 -- n3 signed minimum
32204 CMP @PSP,TOS \ n2-n1
32205 S< ?GOTO BW1 \ n2<n1
32211 : U.R \ u n -- display u unsigned in n width (n >= 2)
32213 R> OVER - 0 MAX SPACES TYPE
32217 CODE 20_US \ n -- n * 20 us
32218 BEGIN \ 3 cycles loop + 6~
32219 \ MOV #5,W \ 3 MCLK = 1 MHz
32220 \ MOV #23,W \ 3 MCLK = 4 MHz
32221 MOV #51,W \ 3 MCLK = 8 MHz
32222 \ MOV #104,W \ 3 MCLK = 16 MHz
32223 \ MOV #158,W \ 3 MCLK = 24 MHz
32224 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
32234 CODE TOP_LCD \ LCD Sample
32235 \ \ if write : %xxxxWWWW --
32236 \ \ if read : -- %0000RRRR
32237 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
32238 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
32239 0= IF \ write LCD bits pattern
32240 AND.B #LCD_DB,TOS \
32241 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
32242 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32245 THEN \ read LCD bits pattern
32248 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32249 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
32250 AND.B #LCD_DB,TOS \
32255 CODE LCD_W \ byte -- write byte to LCD
32257 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
32258 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
32259 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
32260 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
32261 COLON \ high level word starts here
32262 TOP_LCD 2 20_US \ write high nibble first
32267 CODE LCD_WrC \ char -- Write Char
32268 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32273 CODE LCD_WrF \ func -- Write Fonction
32274 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32280 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
32285 $02 LCD_WrF 100 20_us
32289 \ : LCD_Entry_set $04 OR LCD_WrF ;
32291 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
32293 \ : LCD_Display_Shift $10 OR LCD_WrF ;
32295 \ : LCD_Fn_Set $20 OR LCD_WrF ;
32297 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
32299 \ : LCD_Goto $80 OR LCD_WrF ;
32301 \ CODE LCD_R \ -- byte read byte from LCD
32302 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32303 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32304 \ COLON \ starts a FORTH word
32305 \ TOP_LCD 2 20_us \ -- %0000HHHH
32306 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
32307 \ HI2LO \ switch from FORTH to assembler
32308 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
32309 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
32310 \ MOV @RSP+,IP \ restore IP saved by COLON
32315 \ CODE LCD_RdS \ -- status Read Status
32316 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32321 \ CODE LCD_RdC \ -- char Read Char
32322 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32327 \ -------------+------+------+------+------++---+---+---+---+---------+
32328 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
32329 \ -------------+------+------+------+------++---+---+---+---+---------+
32330 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
32331 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
32332 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
32333 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
32334 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
32335 \ -------------+------+------+------+------++---+---+---+---+---------+
32338 \ ******************************\
32339 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32340 \ ******************************\
32341 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
32342 \ ------------------------------\
32343 \ define LPM mode for ACCEPT \
32344 \ ------------------------------\
32345 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32346 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32347 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32348 BIT.B #SW2,&SW2_IN \ test switch S2
32349 0= IF \ case of switch S2 pressed
32350 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
32352 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
32355 BIT.B #SW1,&SW1_IN \ test switch S1 input
32356 0= IF \ case of Switch S1 pressed
32357 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
32359 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
32363 RETI \ CPU is ON, GIE is OFF
32368 \ ------------------------------\
32369 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32370 \ ******************************\
32371 ASM RC5_INT \ wake up on Px.RC5 change interrupt
32372 \ ******************************\
32373 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32374 \ \ SMclock = 8|16|24 MHz
32375 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
32376 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
32377 \ \ SR(9)=new Toggle bit memory (ADD on)
32378 \ ------------------------------\
32379 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
32380 \ ------------------------------\
32381 \ define LPM mode for ACCEPT \
32382 \ ------------------------------\
32383 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32384 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32385 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32386 \ ------------------------------\
32387 \ RC5_FirstStartBitHalfCycle: \
32388 \ ------------------------------\
32389 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
32390 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
32391 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
32392 MOV #1778,X \ RC5_Period in us
32393 MOV #14,W \ count of loop
32395 \ ------------------------------\
32396 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
32397 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
32398 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
32399 \ RC5_Compute_3/4_Period: \ |
32400 RRUM #1,X \ X=1/2 cycle |
32404 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
32405 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
32407 \ ------------------------------\
32408 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
32409 \ ------------------------------\
32410 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32411 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
32412 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32413 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32414 SUB #1,W \ decrement count loop
32415 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
32416 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32417 0<> WHILE \ ----> out of loop ----+
32418 \ RC5_compute_7/4_Time_out: \ |
32419 ADD X,Y \ | out of bound = 7/4 period
32420 \ RC5_WaitHalfCycleP1.2_IFG: \ |
32422 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
32423 0>= IF \ | if cycle time out of bound
32424 BIC #$30,&TA0CTL \ | stop timer_A0
32425 RETI \ | then quit to do nothing
32427 \ ------------------------------\ |
32428 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
32430 MOV &TA0R,X \ | | get new RC5_period value
32431 REPEAT \ ----> loop back --+ |
32432 \ ------------------------------\ |
32433 \ RC5_SampleEndOf: \ <---------------------+
32434 \ ------------------------------\
32435 BIC #$30,&TA0CTL \ stop timer_A0
32436 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
32437 \ ******************************\
32438 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32439 \ ******************************\
32440 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
32441 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
32442 XOR IP,X \ (new XOR old) Toggle bit (13)
32443 BIT #BIT13,X \ X(13) = New_RC5_command
32444 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
32446 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
32447 \ ******************************\
32448 \ RC5_ComputeNewRC5word \
32449 \ ******************************\
32451 MOV &BASE,2(PSP) \ save variable BASE before use
32452 MOV TOS,0(PSP) \ save TOS before use
32453 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
32454 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
32455 \ ******************************\
32456 \ RC5_ComputeC6bit \
32457 \ ******************************\
32458 BIT #$4000,IP \ test /C6 bit in IP
32459 0= IF BIS #$40,TOS \ set C6 bit in S
32460 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
32461 \ ******************************\
32462 \ RC5_CommandByteIsDone \ RC5_code --
32463 \ ******************************\
32465 \ ------------------------------\
32466 \ Display IR_RC5 code \
32467 \ ------------------------------\
32468 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
32469 \ ------------------------------\
32470 LO2HI \ switch from assembler to FORTH
32471 ['] LCD_CLEAR IS CR \ redirects CR
32472 ['] LCD_WrC IS EMIT \ redirects EMIT
32473 $10 BASE ! \ change BASE to hexadecimal
32474 CR ." $" 2 U.R \ print IR_RC5 code
32475 ['] (CR) IS CR \ restore CR
32476 ['] (EMIT) IS EMIT \ restore EMIT
32477 HI2LO \ switch from FORTH to assembler
32478 \ ------------------------------\
32479 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
32480 \ ------------------------------\
32481 MOV @PSP+,&BASE \ restore variable BASE
32482 RETI \ CPU is ON, GIE is OFF
32487 \ ------------------------------\
32488 \ TB0CTL = %0000 0010 1001 0100\$3C0
32489 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32490 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32491 \ -- \ID input divider \ 10 = /4
32492 \ -- \MC Mode Control \ 01 = up to TB0CCR0
32493 \ - \TBCLR TimerB Clear
32496 \ --------------------------------\\
32497 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32498 \ -- \CM Capture Mode
32503 \ --- \OUTMOD \ 011 = set/reset
32509 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
32511 \ ------------------------------\
32512 \ set TimerB to make 50kHz PWM \
32513 \ ------------------------------\
32514 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32515 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
32516 \ ------------------------------\
32517 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32518 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
32519 \ ------------------------------\
32520 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32521 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
32522 \ ------------------------------\
32523 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32524 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
32525 \ ------------------------------\
32526 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32527 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
32528 \ ------------------------------\
32529 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
32530 \ ------------------------------\
32531 \ set TimerB to generate PWM for LCD_Vo
32532 \ ------------------------------\
32533 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
32534 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
32535 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32536 \ ------------------------------\
32537 BIS.B #LCDVo,&LCDVo_DIR \
32538 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
32539 \ ------------------------------\
32540 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32541 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32542 \ ------------------------------\
32543 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32544 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32545 \ ------------------------------\
32546 \ WDT interval init part \
32547 \ ------------------------------\
32548 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
32549 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
32550 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
32551 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
32552 \ ------------------------------\
32554 \ ------------------------------\
32555 BIS.B #RC5,&IR_IE \ enable RC5_Int
32556 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32557 \ ------------------------------\
32558 \ init interrupt vectors
32559 \ ------------------------------\
32560 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
32561 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32562 \ ------------------------------\
32563 \ define LPM mode for ACCEPT \
32564 \ ------------------------------\
32565 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32566 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32567 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32569 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
32571 \ ------------------------------\
32573 \ ------------------------------\
32574 $03E8 20_US \ 1- wait 20 ms
32575 $03 TOP_LCD \ 2- send DB5=DB4=1
32576 $CD 20_US \ 3- wait 4,1 ms
32577 $03 TOP_LCD \ 4- send again DB5=DB4=1
32578 $5 20_US \ 5- wait 0,1 ms
32579 $03 TOP_LCD \ 6- send again again DB5=DB4=1
32580 $2 20_US \ wait 40 us = LCD cycle
32581 $02 TOP_LCD \ 7- send DB5=1 DB4=0
32582 $2 20_US \ wait 40 us = LCD cycle
32583 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32584 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32585 LCD_Clear \ 10- "LCD_Clear"
32586 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32587 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32588 LCD_Clear \ 10- "LCD_Clear"
32589 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32590 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32592 ['] (CR) IS CR \ ' (CR) is CR
32593 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
32595 ." RC5toLCD is running. Type STOP to quit"
32596 \ NOECHO \ uncomment to run this app without terminal connexion
32597 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
32598 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
32602 : STOP \ stops multitasking, must to be used before downloading app
32603 ['] (WARM) IS WARM \ remove START app from FORTH init process
32604 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
32612 CODE MAX \ n1 n2 -- n3 signed maximum
32613 CMP @PSP,TOS \ n2-n1
32614 S< ?GOTO FW1 \ n2<n1
32620 CODE MIN \ n1 n2 -- n3 signed minimum
32621 CMP @PSP,TOS \ n2-n1
32622 S< ?GOTO BW1 \ n2<n1
32628 : U.R \ u n -- display u unsigned in n width (n >= 2)
32630 R> OVER - 0 MAX SPACES TYPE
32634 CODE 20_US \ n -- n * 20 us
32635 BEGIN \ 3 cycles loop + 6~
32636 \ MOV #5,W \ 3 MCLK = 1 MHz
32637 \ MOV #23,W \ 3 MCLK = 4 MHz
32638 MOV #51,W \ 3 MCLK = 8 MHz
32639 \ MOV #104,W \ 3 MCLK = 16 MHz
32640 \ MOV #158,W \ 3 MCLK = 24 MHz
32641 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
32651 CODE TOP_LCD \ LCD Sample
32652 \ \ if write : %xxxxWWWW --
32653 \ \ if read : -- %0000RRRR
32654 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
32655 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
32656 0= IF \ write LCD bits pattern
32657 AND.B #LCD_DB,TOS \
32658 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
32659 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32662 THEN \ read LCD bits pattern
32665 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32666 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
32667 AND.B #LCD_DB,TOS \
32672 CODE LCD_W \ byte -- write byte to LCD
32674 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
32675 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
32676 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
32677 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
32678 COLON \ high level word starts here
32679 TOP_LCD 2 20_US \ write high nibble first
32684 CODE LCD_WrC \ char -- Write Char
32685 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32690 CODE LCD_WrF \ func -- Write Fonction
32691 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32697 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
32702 $02 LCD_WrF 100 20_us
32706 \ : LCD_Entry_set $04 OR LCD_WrF ;
32708 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
32710 \ : LCD_Display_Shift $10 OR LCD_WrF ;
32712 \ : LCD_Fn_Set $20 OR LCD_WrF ;
32714 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
32716 \ : LCD_Goto $80 OR LCD_WrF ;
32718 \ CODE LCD_R \ -- byte read byte from LCD
32719 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32720 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32721 \ COLON \ starts a FORTH word
32722 \ TOP_LCD 2 20_us \ -- %0000HHHH
32723 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
32724 \ HI2LO \ switch from FORTH to assembler
32725 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
32726 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
32727 \ MOV @RSP+,IP \ restore IP saved by COLON
32732 \ CODE LCD_RdS \ -- status Read Status
32733 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32738 \ CODE LCD_RdC \ -- char Read Char
32739 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32744 \ -------------+------+------+------+------++---+---+---+---+---------+
32745 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
32746 \ -------------+------+------+------+------++---+---+---+---+---------+
32747 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
32748 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
32749 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
32750 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
32751 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
32752 \ -------------+------+------+------+------++---+---+---+---+---------+
32755 \ ******************************\
32756 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32757 \ ******************************\
32758 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
32759 \ ------------------------------\
32760 \ define LPM mode for ACCEPT \
32761 \ ------------------------------\
32762 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32763 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32764 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32765 BIT.B #SW2,&SW2_IN \ test switch S2
32766 0= IF \ case of switch S2 pressed
32767 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
32769 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
32772 BIT.B #SW1,&SW1_IN \ test switch S1 input
32773 0= IF \ case of Switch S1 pressed
32774 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
32776 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
32780 RETI \ CPU is ON, GIE is OFF
32785 \ ------------------------------\
32786 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32787 \ ******************************\
32788 ASM RC5_INT \ wake up on Px.RC5 change interrupt
32789 \ ******************************\
32790 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32791 \ \ SMclock = 8|16|24 MHz
32792 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
32793 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
32794 \ \ SR(9)=new Toggle bit memory (ADD on)
32795 \ ------------------------------\
32796 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
32797 \ ------------------------------\
32798 \ define LPM mode for ACCEPT \
32799 \ ------------------------------\
32800 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32801 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32802 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32803 \ ------------------------------\
32804 \ RC5_FirstStartBitHalfCycle: \
32805 \ ------------------------------\
32806 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
32807 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
32808 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
32809 MOV #1778,X \ RC5_Period in us
32810 MOV #14,W \ count of loop
32812 \ ------------------------------\
32813 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
32814 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
32815 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
32816 \ RC5_Compute_3/4_Period: \ |
32817 RRUM #1,X \ X=1/2 cycle |
32821 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
32822 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
32824 \ ------------------------------\
32825 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
32826 \ ------------------------------\
32827 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32828 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
32829 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32830 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32831 SUB #1,W \ decrement count loop
32832 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
32833 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32834 0<> WHILE \ ----> out of loop ----+
32835 \ RC5_compute_7/4_Time_out: \ |
32836 ADD X,Y \ | out of bound = 7/4 period
32837 \ RC5_WaitHalfCycleP1.2_IFG: \ |
32839 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
32840 0>= IF \ | if cycle time out of bound
32841 BIC #$30,&TA0CTL \ | stop timer_A0
32842 RETI \ | then quit to do nothing
32844 \ ------------------------------\ |
32845 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
32847 MOV &TA0R,X \ | | get new RC5_period value
32848 REPEAT \ ----> loop back --+ |
32849 \ ------------------------------\ |
32850 \ RC5_SampleEndOf: \ <---------------------+
32851 \ ------------------------------\
32852 BIC #$30,&TA0CTL \ stop timer_A0
32853 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
32854 \ ******************************\
32855 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32856 \ ******************************\
32857 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
32858 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
32859 XOR IP,X \ (new XOR old) Toggle bit (13)
32860 BIT #BIT13,X \ X(13) = New_RC5_command
32861 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
32863 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
32864 \ ******************************\
32865 \ RC5_ComputeNewRC5word \
32866 \ ******************************\
32868 MOV &BASE,2(PSP) \ save variable BASE before use
32869 MOV TOS,0(PSP) \ save TOS before use
32870 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
32871 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
32872 \ ******************************\
32873 \ RC5_ComputeC6bit \
32874 \ ******************************\
32875 BIT #$4000,IP \ test /C6 bit in IP
32876 0= IF BIS #$40,TOS \ set C6 bit in S
32877 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
32878 \ ******************************\
32879 \ RC5_CommandByteIsDone \ RC5_code --
32880 \ ******************************\
32882 \ ------------------------------\
32883 \ Display IR_RC5 code \
32884 \ ------------------------------\
32885 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
32886 \ ------------------------------\
32887 LO2HI \ switch from assembler to FORTH
32888 ['] LCD_CLEAR IS CR \ redirects CR
32889 ['] LCD_WrC IS EMIT \ redirects EMIT
32890 $10 BASE ! \ change BASE to hexadecimal
32891 CR ." $" 2 U.R \ print IR_RC5 code
32892 ['] (CR) IS CR \ restore CR
32893 ['] (EMIT) IS EMIT \ restore EMIT
32894 HI2LO \ switch from FORTH to assembler
32895 \ ------------------------------\
32896 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
32897 \ ------------------------------\
32898 MOV @PSP+,&BASE \ restore variable BASE
32899 RETI \ CPU is ON, GIE is OFF
32904 \ ------------------------------\
32905 \ TB0CTL = %0000 0010 1001 0100\$3C0
32906 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32907 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32908 \ -- \ID input divider \ 10 = /4
32909 \ -- \MC Mode Control \ 01 = up to TB0CCR0
32910 \ - \TBCLR TimerB Clear
32913 \ --------------------------------\\
32914 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32915 \ -- \CM Capture Mode
32920 \ --- \OUTMOD \ 011 = set/reset
32926 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
32928 \ ------------------------------\
32929 \ set TimerB to make 50kHz PWM \
32930 \ ------------------------------\
32931 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32932 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
32933 \ ------------------------------\
32934 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
32935 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
32936 \ ------------------------------\
32937 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32938 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
32939 \ ------------------------------\
32940 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32941 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
32942 \ ------------------------------\
32943 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
32944 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
32945 \ ------------------------------\
32946 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
32947 \ ------------------------------\
32948 \ set TimerB to generate PWM for LCD_Vo
32949 \ ------------------------------\
32950 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
32951 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
32952 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32953 \ ------------------------------\
32954 BIS.B #LCDVo,&LCDVo_DIR \
32955 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
32956 \ ------------------------------\
32957 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32958 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32959 \ ------------------------------\
32960 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32961 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32962 \ ------------------------------\
32963 \ WDT interval init part \
32964 \ ------------------------------\
32965 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
32966 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
32967 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
32968 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
32969 \ ------------------------------\
32971 \ ------------------------------\
32972 BIS.B #RC5,&IR_IE \ enable RC5_Int
32973 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32974 \ ------------------------------\
32975 \ init interrupt vectors
32976 \ ------------------------------\
32977 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
32978 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32979 \ ------------------------------\
32980 \ define LPM mode for ACCEPT \
32981 \ ------------------------------\
32982 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32983 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32984 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32986 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
32988 \ ------------------------------\
32990 \ ------------------------------\
32991 $03E8 20_US \ 1- wait 20 ms
32992 $03 TOP_LCD \ 2- send DB5=DB4=1
32993 $CD 20_US \ 3- wait 4,1 ms
32994 $03 TOP_LCD \ 4- send again DB5=DB4=1
32995 $5 20_US \ 5- wait 0,1 ms
32996 $03 TOP_LCD \ 6- send again again DB5=DB4=1
32997 $2 20_US \ wait 40 us = LCD cycle
32998 $02 TOP_LCD \ 7- send DB5=1 DB4=0
32999 $2 20_US \ wait 40 us = LCD cycle
33000 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33001 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33002 LCD_Clear \ 10- "LCD_Clear"
33003 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33004 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33005 LCD_Clear \ 10- "LCD_Clear"
33006 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33007 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33009 ['] (CR) IS CR \ ' (CR) is CR
33010 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
33012 ." RC5toLCD is running. Type STOP to quit"
33013 \ NOECHO \ uncomment to run this app without terminal connexion
33014 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
33015 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
33019 : STOP \ stops multitasking, must to be used before downloading app
33020 ['] (WARM) IS WARM \ remove START app from FORTH init process
33021 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
33029 CODE MAX \ n1 n2 -- n3 signed maximum
33030 CMP @PSP,TOS \ n2-n1
33031 S< ?GOTO FW1 \ n2<n1
33037 CODE MIN \ n1 n2 -- n3 signed minimum
33038 CMP @PSP,TOS \ n2-n1
33039 S< ?GOTO BW1 \ n2<n1
33045 : U.R \ u n -- display u unsigned in n width (n >= 2)
33047 R> OVER - 0 MAX SPACES TYPE
33051 CODE 20_US \ n -- n * 20 us
33052 BEGIN \ 3 cycles loop + 6~
33053 \ MOV #5,W \ 3 MCLK = 1 MHz
33054 \ MOV #23,W \ 3 MCLK = 4 MHz
33055 MOV #51,W \ 3 MCLK = 8 MHz
33056 \ MOV #104,W \ 3 MCLK = 16 MHz
33057 \ MOV #158,W \ 3 MCLK = 24 MHz
33058 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
33068 CODE TOP_LCD \ LCD Sample
33069 \ \ if write : %xxxxWWWW --
33070 \ \ if read : -- %0000RRRR
33071 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33072 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33073 0= IF \ write LCD bits pattern
33074 AND.B #LCD_DB,TOS \
33075 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33076 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33079 THEN \ read LCD bits pattern
33082 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33083 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33084 AND.B #LCD_DB,TOS \
33089 CODE LCD_W \ byte -- write byte to LCD
33091 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
33092 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
33093 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33094 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33095 COLON \ high level word starts here
33096 TOP_LCD 2 20_US \ write high nibble first
33101 CODE LCD_WrC \ char -- Write Char
33102 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33107 CODE LCD_WrF \ func -- Write Fonction
33108 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33114 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
33119 $02 LCD_WrF 100 20_us
33123 \ : LCD_Entry_set $04 OR LCD_WrF ;
33125 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
33127 \ : LCD_Display_Shift $10 OR LCD_WrF ;
33129 \ : LCD_Fn_Set $20 OR LCD_WrF ;
33131 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
33133 \ : LCD_Goto $80 OR LCD_WrF ;
33135 \ CODE LCD_R \ -- byte read byte from LCD
33136 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33137 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33138 \ COLON \ starts a FORTH word
33139 \ TOP_LCD 2 20_us \ -- %0000HHHH
33140 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
33141 \ HI2LO \ switch from FORTH to assembler
33142 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
33143 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
33144 \ MOV @RSP+,IP \ restore IP saved by COLON
33149 \ CODE LCD_RdS \ -- status Read Status
33150 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33155 \ CODE LCD_RdC \ -- char Read Char
33156 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33161 \ -------------+------+------+------+------++---+---+---+---+---------+
33162 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
33163 \ -------------+------+------+------+------++---+---+---+---+---------+
33164 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
33165 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
33166 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
33167 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
33168 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
33169 \ -------------+------+------+------+------++---+---+---+---+---------+
33172 \ ******************************\
33173 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33174 \ ******************************\
33175 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
33176 \ ------------------------------\
33177 \ define LPM mode for ACCEPT \
33178 \ ------------------------------\
33179 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33180 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33181 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33182 BIT.B #SW2,&SW2_IN \ test switch S2
33183 0= IF \ case of switch S2 pressed
33184 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
33186 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
33189 BIT.B #SW1,&SW1_IN \ test switch S1 input
33190 0= IF \ case of Switch S1 pressed
33191 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
33193 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
33197 RETI \ CPU is ON, GIE is OFF
33202 \ ------------------------------\
33203 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33204 \ ******************************\
33205 ASM RC5_INT \ wake up on Px.RC5 change interrupt
33206 \ ******************************\
33207 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33208 \ \ SMclock = 8|16|24 MHz
33209 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
33210 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
33211 \ \ SR(9)=new Toggle bit memory (ADD on)
33212 \ ------------------------------\
33213 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
33214 \ ------------------------------\
33215 \ define LPM mode for ACCEPT \
33216 \ ------------------------------\
33217 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33218 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33219 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33220 \ ------------------------------\
33221 \ RC5_FirstStartBitHalfCycle: \
33222 \ ------------------------------\
33223 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
33224 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
33225 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
33226 MOV #1778,X \ RC5_Period in us
33227 MOV #14,W \ count of loop
33229 \ ------------------------------\
33230 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
33231 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
33232 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
33233 \ RC5_Compute_3/4_Period: \ |
33234 RRUM #1,X \ X=1/2 cycle |
33238 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
33239 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
33241 \ ------------------------------\
33242 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
33243 \ ------------------------------\
33244 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33245 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
33246 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33247 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33248 SUB #1,W \ decrement count loop
33249 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
33250 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33251 0<> WHILE \ ----> out of loop ----+
33252 \ RC5_compute_7/4_Time_out: \ |
33253 ADD X,Y \ | out of bound = 7/4 period
33254 \ RC5_WaitHalfCycleP1.2_IFG: \ |
33256 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
33257 0>= IF \ | if cycle time out of bound
33258 BIC #$30,&TA0CTL \ | stop timer_A0
33259 RETI \ | then quit to do nothing
33261 \ ------------------------------\ |
33262 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
33264 MOV &TA0R,X \ | | get new RC5_period value
33265 REPEAT \ ----> loop back --+ |
33266 \ ------------------------------\ |
33267 \ RC5_SampleEndOf: \ <---------------------+
33268 \ ------------------------------\
33269 BIC #$30,&TA0CTL \ stop timer_A0
33270 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
33271 \ ******************************\
33272 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
33273 \ ******************************\
33274 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
33275 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
33276 XOR IP,X \ (new XOR old) Toggle bit (13)
33277 BIT #BIT13,X \ X(13) = New_RC5_command
33278 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
33280 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
33281 \ ******************************\
33282 \ RC5_ComputeNewRC5word \
33283 \ ******************************\
33285 MOV &BASE,2(PSP) \ save variable BASE before use
33286 MOV TOS,0(PSP) \ save TOS before use
33287 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
33288 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
33289 \ ******************************\
33290 \ RC5_ComputeC6bit \
33291 \ ******************************\
33292 BIT #$4000,IP \ test /C6 bit in IP
33293 0= IF BIS #$40,TOS \ set C6 bit in S
33294 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
33295 \ ******************************\
33296 \ RC5_CommandByteIsDone \ RC5_code --
33297 \ ******************************\
33299 \ ------------------------------\
33300 \ Display IR_RC5 code \
33301 \ ------------------------------\
33302 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
33303 \ ------------------------------\
33304 LO2HI \ switch from assembler to FORTH
33305 ['] LCD_CLEAR IS CR \ redirects CR
33306 ['] LCD_WrC IS EMIT \ redirects EMIT
33307 $10 BASE ! \ change BASE to hexadecimal
33308 CR ." $" 2 U.R \ print IR_RC5 code
33309 ['] (CR) IS CR \ restore CR
33310 ['] (EMIT) IS EMIT \ restore EMIT
33311 HI2LO \ switch from FORTH to assembler
33312 \ ------------------------------\
33313 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
33314 \ ------------------------------\
33315 MOV @PSP+,&BASE \ restore variable BASE
33316 RETI \ CPU is ON, GIE is OFF
33321 \ ------------------------------\
33322 \ TB0CTL = %0000 0010 1001 0100\$3C0
33323 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33324 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33325 \ -- \ID input divider \ 10 = /4
33326 \ -- \MC Mode Control \ 01 = up to TB0CCR0
33327 \ - \TBCLR TimerB Clear
33330 \ --------------------------------\\
33331 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33332 \ -- \CM Capture Mode
33337 \ --- \OUTMOD \ 011 = set/reset
33343 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
33345 \ ------------------------------\
33346 \ set TimerB to make 50kHz PWM \
33347 \ ------------------------------\
33348 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33349 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
33350 \ ------------------------------\
33351 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33352 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
33353 \ ------------------------------\
33354 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33355 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
33356 \ ------------------------------\
33357 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33358 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
33359 \ ------------------------------\
33360 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33361 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
33362 \ ------------------------------\
33363 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
33364 \ ------------------------------\
33365 \ set TimerB to generate PWM for LCD_Vo
33366 \ ------------------------------\
33367 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
33368 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
33369 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33370 \ ------------------------------\
33371 BIS.B #LCDVo,&LCDVo_DIR \
33372 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
33373 \ ------------------------------\
33374 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33375 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33376 \ ------------------------------\
33377 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33378 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33379 \ ------------------------------\
33380 \ WDT interval init part \
33381 \ ------------------------------\
33382 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
33383 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
33384 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
33385 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
33386 \ ------------------------------\
33388 \ ------------------------------\
33389 BIS.B #RC5,&IR_IE \ enable RC5_Int
33390 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33391 \ ------------------------------\
33392 \ init interrupt vectors
33393 \ ------------------------------\
33394 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
33395 MOV #RC5_INT,&IR_Vec \ init interrupt vector
33396 \ ------------------------------\
33397 \ define LPM mode for ACCEPT \
33398 \ ------------------------------\
33399 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33400 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33401 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33403 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
33405 \ ------------------------------\
33407 \ ------------------------------\
33408 $03E8 20_US \ 1- wait 20 ms
33409 $03 TOP_LCD \ 2- send DB5=DB4=1
33410 $CD 20_US \ 3- wait 4,1 ms
33411 $03 TOP_LCD \ 4- send again DB5=DB4=1
33412 $5 20_US \ 5- wait 0,1 ms
33413 $03 TOP_LCD \ 6- send again again DB5=DB4=1
33414 $2 20_US \ wait 40 us = LCD cycle
33415 $02 TOP_LCD \ 7- send DB5=1 DB4=0
33416 $2 20_US \ wait 40 us = LCD cycle
33417 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33418 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33419 LCD_Clear \ 10- "LCD_Clear"
33420 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33421 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33422 LCD_Clear \ 10- "LCD_Clear"
33423 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33424 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33426 ['] (CR) IS CR \ ' (CR) is CR
33427 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
33429 ." RC5toLCD is running. Type STOP to quit"
33430 \ NOECHO \ uncomment to run this app without terminal connexion
33431 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
33432 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
33436 : STOP \ stops multitasking, must to be used before downloading app
33437 ['] (WARM) IS WARM \ remove START app from FORTH init process
33438 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
33446 CODE MAX \ n1 n2 -- n3 signed maximum
33447 CMP @PSP,TOS \ n2-n1
33448 S< ?GOTO FW1 \ n2<n1
33454 CODE MIN \ n1 n2 -- n3 signed minimum
33455 CMP @PSP,TOS \ n2-n1
33456 S< ?GOTO BW1 \ n2<n1
33462 : U.R \ u n -- display u unsigned in n width (n >= 2)
33464 R> OVER - 0 MAX SPACES TYPE
33468 CODE 20_US \ n -- n * 20 us
33469 BEGIN \ 3 cycles loop + 6~
33470 \ MOV #5,W \ 3 MCLK = 1 MHz
33471 \ MOV #23,W \ 3 MCLK = 4 MHz
33472 MOV #51,W \ 3 MCLK = 8 MHz
33473 \ MOV #104,W \ 3 MCLK = 16 MHz
33474 \ MOV #158,W \ 3 MCLK = 24 MHz
33475 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
33485 CODE TOP_LCD \ LCD Sample
33486 \ \ if write : %xxxxWWWW --
33487 \ \ if read : -- %0000RRRR
33488 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33489 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33490 0= IF \ write LCD bits pattern
33491 AND.B #LCD_DB,TOS \
33492 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33493 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33496 THEN \ read LCD bits pattern
33499 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33500 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33501 AND.B #LCD_DB,TOS \
33506 CODE LCD_W \ byte -- write byte to LCD
33508 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
33509 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
33510 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33511 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33512 COLON \ high level word starts here
33513 TOP_LCD 2 20_US \ write high nibble first
33518 CODE LCD_WrC \ char -- Write Char
33519 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33524 CODE LCD_WrF \ func -- Write Fonction
33525 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33531 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
33536 $02 LCD_WrF 100 20_us
33540 \ : LCD_Entry_set $04 OR LCD_WrF ;
33542 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
33544 \ : LCD_Display_Shift $10 OR LCD_WrF ;
33546 \ : LCD_Fn_Set $20 OR LCD_WrF ;
33548 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
33550 \ : LCD_Goto $80 OR LCD_WrF ;
33552 \ CODE LCD_R \ -- byte read byte from LCD
33553 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33554 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33555 \ COLON \ starts a FORTH word
33556 \ TOP_LCD 2 20_us \ -- %0000HHHH
33557 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
33558 \ HI2LO \ switch from FORTH to assembler
33559 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
33560 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
33561 \ MOV @RSP+,IP \ restore IP saved by COLON
33566 \ CODE LCD_RdS \ -- status Read Status
33567 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33572 \ CODE LCD_RdC \ -- char Read Char
33573 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33578 \ -------------+------+------+------+------++---+---+---+---+---------+
33579 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
33580 \ -------------+------+------+------+------++---+---+---+---+---------+
33581 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
33582 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
33583 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
33584 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
33585 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
33586 \ -------------+------+------+------+------++---+---+---+---+---------+
33589 \ ******************************\
33590 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33591 \ ******************************\
33592 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
33593 \ ------------------------------\
33594 \ define LPM mode for ACCEPT \
33595 \ ------------------------------\
33596 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33597 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33598 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33599 BIT.B #SW2,&SW2_IN \ test switch S2
33600 0= IF \ case of switch S2 pressed
33601 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
33603 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
33606 BIT.B #SW1,&SW1_IN \ test switch S1 input
33607 0= IF \ case of Switch S1 pressed
33608 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
33610 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
33614 RETI \ CPU is ON, GIE is OFF
33619 \ ------------------------------\
33620 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33621 \ ******************************\
33622 ASM RC5_INT \ wake up on Px.RC5 change interrupt
33623 \ ******************************\
33624 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33625 \ \ SMclock = 8|16|24 MHz
33626 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
33627 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
33628 \ \ SR(9)=new Toggle bit memory (ADD on)
33629 \ ------------------------------\
33630 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
33631 \ ------------------------------\
33632 \ define LPM mode for ACCEPT \
33633 \ ------------------------------\
33634 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33635 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33636 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33637 \ ------------------------------\
33638 \ RC5_FirstStartBitHalfCycle: \
33639 \ ------------------------------\
33640 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
33641 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
33642 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
33643 MOV #1778,X \ RC5_Period in us
33644 MOV #14,W \ count of loop
33646 \ ------------------------------\
33647 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
33648 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
33649 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
33650 \ RC5_Compute_3/4_Period: \ |
33651 RRUM #1,X \ X=1/2 cycle |
33655 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
33656 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
33658 \ ------------------------------\
33659 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
33660 \ ------------------------------\
33661 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33662 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
33663 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33664 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33665 SUB #1,W \ decrement count loop
33666 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
33667 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33668 0<> WHILE \ ----> out of loop ----+
33669 \ RC5_compute_7/4_Time_out: \ |
33670 ADD X,Y \ | out of bound = 7/4 period
33671 \ RC5_WaitHalfCycleP1.2_IFG: \ |
33673 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
33674 0>= IF \ | if cycle time out of bound
33675 BIC #$30,&TA0CTL \ | stop timer_A0
33676 RETI \ | then quit to do nothing
33678 \ ------------------------------\ |
33679 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
33681 MOV &TA0R,X \ | | get new RC5_period value
33682 REPEAT \ ----> loop back --+ |
33683 \ ------------------------------\ |
33684 \ RC5_SampleEndOf: \ <---------------------+
33685 \ ------------------------------\
33686 BIC #$30,&TA0CTL \ stop timer_A0
33687 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
33688 \ ******************************\
33689 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
33690 \ ******************************\
33691 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
33692 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
33693 XOR IP,X \ (new XOR old) Toggle bit (13)
33694 BIT #BIT13,X \ X(13) = New_RC5_command
33695 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
33697 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
33698 \ ******************************\
33699 \ RC5_ComputeNewRC5word \
33700 \ ******************************\
33702 MOV &BASE,2(PSP) \ save variable BASE before use
33703 MOV TOS,0(PSP) \ save TOS before use
33704 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
33705 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
33706 \ ******************************\
33707 \ RC5_ComputeC6bit \
33708 \ ******************************\
33709 BIT #$4000,IP \ test /C6 bit in IP
33710 0= IF BIS #$40,TOS \ set C6 bit in S
33711 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
33712 \ ******************************\
33713 \ RC5_CommandByteIsDone \ RC5_code --
33714 \ ******************************\
33716 \ ------------------------------\
33717 \ Display IR_RC5 code \
33718 \ ------------------------------\
33719 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
33720 \ ------------------------------\
33721 LO2HI \ switch from assembler to FORTH
33722 ['] LCD_CLEAR IS CR \ redirects CR
33723 ['] LCD_WrC IS EMIT \ redirects EMIT
33724 $10 BASE ! \ change BASE to hexadecimal
33725 CR ." $" 2 U.R \ print IR_RC5 code
33726 ['] (CR) IS CR \ restore CR
33727 ['] (EMIT) IS EMIT \ restore EMIT
33728 HI2LO \ switch from FORTH to assembler
33729 \ ------------------------------\
33730 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
33731 \ ------------------------------\
33732 MOV @PSP+,&BASE \ restore variable BASE
33733 RETI \ CPU is ON, GIE is OFF
33738 \ ------------------------------\
33739 \ TB0CTL = %0000 0010 1001 0100\$3C0
33740 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33741 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33742 \ -- \ID input divider \ 10 = /4
33743 \ -- \MC Mode Control \ 01 = up to TB0CCR0
33744 \ - \TBCLR TimerB Clear
33747 \ --------------------------------\\
33748 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33749 \ -- \CM Capture Mode
33754 \ --- \OUTMOD \ 011 = set/reset
33760 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
33762 \ ------------------------------\
33763 \ set TimerB to make 50kHz PWM \
33764 \ ------------------------------\
33765 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33766 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
33767 \ ------------------------------\
33768 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
33769 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
33770 \ ------------------------------\
33771 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33772 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
33773 \ ------------------------------\
33774 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33775 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
33776 \ ------------------------------\
33777 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
33778 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
33779 \ ------------------------------\
33780 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
33781 \ ------------------------------\
33782 \ set TimerB to generate PWM for LCD_Vo
33783 \ ------------------------------\
33784 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
33785 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
33786 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33787 \ ------------------------------\
33788 BIS.B #LCDVo,&LCDVo_DIR \
33789 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
33790 \ ------------------------------\
33791 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33792 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33793 \ ------------------------------\
33794 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33795 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33796 \ ------------------------------\
33797 \ WDT interval init part \
33798 \ ------------------------------\
33799 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
33800 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
33801 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
33802 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
33803 \ ------------------------------\
33805 \ ------------------------------\
33806 BIS.B #RC5,&IR_IE \ enable RC5_Int
33807 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33808 \ ------------------------------\
33809 \ init interrupt vectors
33810 \ ------------------------------\
33811 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
33812 MOV #RC5_INT,&IR_Vec \ init interrupt vector
33813 \ ------------------------------\
33814 \ define LPM mode for ACCEPT \
33815 \ ------------------------------\
33816 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33817 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33818 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33820 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
33822 \ ------------------------------\
33824 \ ------------------------------\
33825 $03E8 20_US \ 1- wait 20 ms
33826 $03 TOP_LCD \ 2- send DB5=DB4=1
33827 $CD 20_US \ 3- wait 4,1 ms
33828 $03 TOP_LCD \ 4- send again DB5=DB4=1
33829 $5 20_US \ 5- wait 0,1 ms
33830 $03 TOP_LCD \ 6- send again again DB5=DB4=1
33831 $2 20_US \ wait 40 us = LCD cycle
33832 $02 TOP_LCD \ 7- send DB5=1 DB4=0
33833 $2 20_US \ wait 40 us = LCD cycle
33834 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33835 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33836 LCD_Clear \ 10- "LCD_Clear"
33837 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33838 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33839 LCD_Clear \ 10- "LCD_Clear"
33840 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33841 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33843 ['] (CR) IS CR \ ' (CR) is CR
33844 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
33846 ." RC5toLCD is running. Type STOP to quit"
33847 \ NOECHO \ uncomment to run this app without terminal connexion
33848 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
33849 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
33853 : STOP \ stops multitasking, must to be used before downloading app
33854 ['] (WARM) IS WARM \ remove START app from FORTH init process
33855 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
33863 CODE MAX \ n1 n2 -- n3 signed maximum
33864 CMP @PSP,TOS \ n2-n1
33865 S< ?GOTO FW1 \ n2<n1
33871 CODE MIN \ n1 n2 -- n3 signed minimum
33872 CMP @PSP,TOS \ n2-n1
33873 S< ?GOTO BW1 \ n2<n1
33879 : U.R \ u n -- display u unsigned in n width (n >= 2)
33881 R> OVER - 0 MAX SPACES TYPE
33885 CODE 20_US \ n -- n * 20 us
33886 BEGIN \ 3 cycles loop + 6~
33887 \ MOV #5,W \ 3 MCLK = 1 MHz
33888 \ MOV #23,W \ 3 MCLK = 4 MHz
33889 MOV #51,W \ 3 MCLK = 8 MHz
33890 \ MOV #104,W \ 3 MCLK = 16 MHz
33891 \ MOV #158,W \ 3 MCLK = 24 MHz
33892 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
33902 CODE TOP_LCD \ LCD Sample
33903 \ \ if write : %xxxxWWWW --
33904 \ \ if read : -- %0000RRRR
33905 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33906 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33907 0= IF \ write LCD bits pattern
33908 AND.B #LCD_DB,TOS \
33909 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33910 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33913 THEN \ read LCD bits pattern
33916 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33917 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33918 AND.B #LCD_DB,TOS \
33923 CODE LCD_W \ byte -- write byte to LCD
33925 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
33926 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
33927 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33928 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33929 COLON \ high level word starts here
33930 TOP_LCD 2 20_US \ write high nibble first
33935 CODE LCD_WrC \ char -- Write Char
33936 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33941 CODE LCD_WrF \ func -- Write Fonction
33942 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33948 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
33953 $02 LCD_WrF 100 20_us
33957 \ : LCD_Entry_set $04 OR LCD_WrF ;
33959 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
33961 \ : LCD_Display_Shift $10 OR LCD_WrF ;
33963 \ : LCD_Fn_Set $20 OR LCD_WrF ;
33965 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
33967 \ : LCD_Goto $80 OR LCD_WrF ;
33969 \ CODE LCD_R \ -- byte read byte from LCD
33970 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33971 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33972 \ COLON \ starts a FORTH word
33973 \ TOP_LCD 2 20_us \ -- %0000HHHH
33974 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
33975 \ HI2LO \ switch from FORTH to assembler
33976 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
33977 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
33978 \ MOV @RSP+,IP \ restore IP saved by COLON
33983 \ CODE LCD_RdS \ -- status Read Status
33984 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33989 \ CODE LCD_RdC \ -- char Read Char
33990 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33995 \ -------------+------+------+------+------++---+---+---+---+---------+
33996 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
33997 \ -------------+------+------+------+------++---+---+---+---+---------+
33998 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
33999 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
34000 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
34001 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
34002 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
34003 \ -------------+------+------+------+------++---+---+---+---+---------+
34006 \ ******************************\
34007 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34008 \ ******************************\
34009 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
34010 \ ------------------------------\
34011 \ define LPM mode for ACCEPT \
34012 \ ------------------------------\
34013 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34014 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34015 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34016 BIT.B #SW2,&SW2_IN \ test switch S2
34017 0= IF \ case of switch S2 pressed
34018 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
34020 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
34023 BIT.B #SW1,&SW1_IN \ test switch S1 input
34024 0= IF \ case of Switch S1 pressed
34025 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
34027 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
34031 RETI \ CPU is ON, GIE is OFF
34036 \ ------------------------------\
34037 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34038 \ ******************************\
34039 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34040 \ ******************************\
34041 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34042 \ \ SMclock = 8|16|24 MHz
34043 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
34044 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
34045 \ \ SR(9)=new Toggle bit memory (ADD on)
34046 \ ------------------------------\
34047 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
34048 \ ------------------------------\
34049 \ define LPM mode for ACCEPT \
34050 \ ------------------------------\
34051 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34052 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34053 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34054 \ ------------------------------\
34055 \ RC5_FirstStartBitHalfCycle: \
34056 \ ------------------------------\
34057 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
34058 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
34059 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
34060 MOV #1778,X \ RC5_Period in us
34061 MOV #14,W \ count of loop
34063 \ ------------------------------\
34064 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
34065 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
34066 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
34067 \ RC5_Compute_3/4_Period: \ |
34068 RRUM #1,X \ X=1/2 cycle |
34072 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
34073 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
34075 \ ------------------------------\
34076 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
34077 \ ------------------------------\
34078 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34079 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
34080 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34081 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34082 SUB #1,W \ decrement count loop
34083 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
34084 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34085 0<> WHILE \ ----> out of loop ----+
34086 \ RC5_compute_7/4_Time_out: \ |
34087 ADD X,Y \ | out of bound = 7/4 period
34088 \ RC5_WaitHalfCycleP1.2_IFG: \ |
34090 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
34091 0>= IF \ | if cycle time out of bound
34092 BIC #$30,&TA0CTL \ | stop timer_A0
34093 RETI \ | then quit to do nothing
34095 \ ------------------------------\ |
34096 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
34098 MOV &TA0R,X \ | | get new RC5_period value
34099 REPEAT \ ----> loop back --+ |
34100 \ ------------------------------\ |
34101 \ RC5_SampleEndOf: \ <---------------------+
34102 \ ------------------------------\
34103 BIC #$30,&TA0CTL \ stop timer_A0
34104 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
34105 \ ******************************\
34106 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34107 \ ******************************\
34108 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
34109 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
34110 XOR IP,X \ (new XOR old) Toggle bit (13)
34111 BIT #BIT13,X \ X(13) = New_RC5_command
34112 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
34114 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
34115 \ ******************************\
34116 \ RC5_ComputeNewRC5word \
34117 \ ******************************\
34119 MOV &BASE,2(PSP) \ save variable BASE before use
34120 MOV TOS,0(PSP) \ save TOS before use
34121 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
34122 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
34123 \ ******************************\
34124 \ RC5_ComputeC6bit \
34125 \ ******************************\
34126 BIT #$4000,IP \ test /C6 bit in IP
34127 0= IF BIS #$40,TOS \ set C6 bit in S
34128 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
34129 \ ******************************\
34130 \ RC5_CommandByteIsDone \ RC5_code --
34131 \ ******************************\
34133 \ ------------------------------\
34134 \ Display IR_RC5 code \
34135 \ ------------------------------\
34136 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
34137 \ ------------------------------\
34138 LO2HI \ switch from assembler to FORTH
34139 ['] LCD_CLEAR IS CR \ redirects CR
34140 ['] LCD_WrC IS EMIT \ redirects EMIT
34141 $10 BASE ! \ change BASE to hexadecimal
34142 CR ." $" 2 U.R \ print IR_RC5 code
34143 ['] (CR) IS CR \ restore CR
34144 ['] (EMIT) IS EMIT \ restore EMIT
34145 HI2LO \ switch from FORTH to assembler
34146 \ ------------------------------\
34147 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
34148 \ ------------------------------\
34149 MOV @PSP+,&BASE \ restore variable BASE
34150 RETI \ CPU is ON, GIE is OFF
34155 \ ------------------------------\
34156 \ TB0CTL = %0000 0010 1001 0100\$3C0
34157 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34158 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34159 \ -- \ID input divider \ 10 = /4
34160 \ -- \MC Mode Control \ 01 = up to TB0CCR0
34161 \ - \TBCLR TimerB Clear
34164 \ --------------------------------\\
34165 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34166 \ -- \CM Capture Mode
34171 \ --- \OUTMOD \ 011 = set/reset
34177 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
34179 \ ------------------------------\
34180 \ set TimerB to make 50kHz PWM \
34181 \ ------------------------------\
34182 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34183 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
34184 \ ------------------------------\
34185 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34186 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
34187 \ ------------------------------\
34188 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34189 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
34190 \ ------------------------------\
34191 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34192 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
34193 \ ------------------------------\
34194 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34195 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
34196 \ ------------------------------\
34197 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
34198 \ ------------------------------\
34199 \ set TimerB to generate PWM for LCD_Vo
34200 \ ------------------------------\
34201 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
34202 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
34203 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34204 \ ------------------------------\
34205 BIS.B #LCDVo,&LCDVo_DIR \
34206 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
34207 \ ------------------------------\
34208 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34209 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34210 \ ------------------------------\
34211 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
34212 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
34213 \ ------------------------------\
34214 \ WDT interval init part \
34215 \ ------------------------------\
34216 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
34217 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
34218 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
34219 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
34220 \ ------------------------------\
34222 \ ------------------------------\
34223 BIS.B #RC5,&IR_IE \ enable RC5_Int
34224 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
34225 \ ------------------------------\
34226 \ init interrupt vectors
34227 \ ------------------------------\
34228 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
34229 MOV #RC5_INT,&IR_Vec \ init interrupt vector
34230 \ ------------------------------\
34231 \ define LPM mode for ACCEPT \
34232 \ ------------------------------\
34233 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34234 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34235 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34237 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
34239 \ ------------------------------\
34241 \ ------------------------------\
34242 $03E8 20_US \ 1- wait 20 ms
34243 $03 TOP_LCD \ 2- send DB5=DB4=1
34244 $CD 20_US \ 3- wait 4,1 ms
34245 $03 TOP_LCD \ 4- send again DB5=DB4=1
34246 $5 20_US \ 5- wait 0,1 ms
34247 $03 TOP_LCD \ 6- send again again DB5=DB4=1
34248 $2 20_US \ wait 40 us = LCD cycle
34249 $02 TOP_LCD \ 7- send DB5=1 DB4=0
34250 $2 20_US \ wait 40 us = LCD cycle
34251 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34252 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34253 LCD_Clear \ 10- "LCD_Clear"
34254 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34255 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34256 LCD_Clear \ 10- "LCD_Clear"
34257 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34258 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34260 ['] (CR) IS CR \ ' (CR) is CR
34261 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
34263 ." RC5toLCD is running. Type STOP to quit"
34264 \ NOECHO \ uncomment to run this app without terminal connexion
34265 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
34266 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
34270 : STOP \ stops multitasking, must to be used before downloading app
34271 ['] (WARM) IS WARM \ remove START app from FORTH init process
34272 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
34280 CODE MAX \ n1 n2 -- n3 signed maximum
34281 CMP @PSP,TOS \ n2-n1
34282 S< ?GOTO FW1 \ n2<n1
34288 CODE MIN \ n1 n2 -- n3 signed minimum
34289 CMP @PSP,TOS \ n2-n1
34290 S< ?GOTO BW1 \ n2<n1
34296 : U.R \ u n -- display u unsigned in n width (n >= 2)
34298 R> OVER - 0 MAX SPACES TYPE
34302 CODE 20_US \ n -- n * 20 us
34303 BEGIN \ 3 cycles loop + 6~
34304 \ MOV #5,W \ 3 MCLK = 1 MHz
34305 \ MOV #23,W \ 3 MCLK = 4 MHz
34306 MOV #51,W \ 3 MCLK = 8 MHz
34307 \ MOV #104,W \ 3 MCLK = 16 MHz
34308 \ MOV #158,W \ 3 MCLK = 24 MHz
34309 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
34319 CODE TOP_LCD \ LCD Sample
34320 \ \ if write : %xxxxWWWW --
34321 \ \ if read : -- %0000RRRR
34322 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34323 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34324 0= IF \ write LCD bits pattern
34325 AND.B #LCD_DB,TOS \
34326 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34327 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34330 THEN \ read LCD bits pattern
34333 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34334 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34335 AND.B #LCD_DB,TOS \
34340 CODE LCD_W \ byte -- write byte to LCD
34342 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
34343 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
34344 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34345 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34346 COLON \ high level word starts here
34347 TOP_LCD 2 20_US \ write high nibble first
34352 CODE LCD_WrC \ char -- Write Char
34353 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34358 CODE LCD_WrF \ func -- Write Fonction
34359 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34365 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
34370 $02 LCD_WrF 100 20_us
34374 \ : LCD_Entry_set $04 OR LCD_WrF ;
34376 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
34378 \ : LCD_Display_Shift $10 OR LCD_WrF ;
34380 \ : LCD_Fn_Set $20 OR LCD_WrF ;
34382 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
34384 \ : LCD_Goto $80 OR LCD_WrF ;
34386 \ CODE LCD_R \ -- byte read byte from LCD
34387 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34388 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34389 \ COLON \ starts a FORTH word
34390 \ TOP_LCD 2 20_us \ -- %0000HHHH
34391 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
34392 \ HI2LO \ switch from FORTH to assembler
34393 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
34394 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
34395 \ MOV @RSP+,IP \ restore IP saved by COLON
34400 \ CODE LCD_RdS \ -- status Read Status
34401 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34406 \ CODE LCD_RdC \ -- char Read Char
34407 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34412 \ -------------+------+------+------+------++---+---+---+---+---------+
34413 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
34414 \ -------------+------+------+------+------++---+---+---+---+---------+
34415 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
34416 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
34417 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
34418 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
34419 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
34420 \ -------------+------+------+------+------++---+---+---+---+---------+
34423 \ ******************************\
34424 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34425 \ ******************************\
34426 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
34427 \ ------------------------------\
34428 \ define LPM mode for ACCEPT \
34429 \ ------------------------------\
34430 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34431 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34432 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34433 BIT.B #SW2,&SW2_IN \ test switch S2
34434 0= IF \ case of switch S2 pressed
34435 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
34437 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
34440 BIT.B #SW1,&SW1_IN \ test switch S1 input
34441 0= IF \ case of Switch S1 pressed
34442 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
34444 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
34448 RETI \ CPU is ON, GIE is OFF
34453 \ ------------------------------\
34454 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34455 \ ******************************\
34456 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34457 \ ******************************\
34458 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34459 \ \ SMclock = 8|16|24 MHz
34460 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
34461 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
34462 \ \ SR(9)=new Toggle bit memory (ADD on)
34463 \ ------------------------------\
34464 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
34465 \ ------------------------------\
34466 \ define LPM mode for ACCEPT \
34467 \ ------------------------------\
34468 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34469 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34470 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34471 \ ------------------------------\
34472 \ RC5_FirstStartBitHalfCycle: \
34473 \ ------------------------------\
34474 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
34475 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
34476 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
34477 MOV #1778,X \ RC5_Period in us
34478 MOV #14,W \ count of loop
34480 \ ------------------------------\
34481 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
34482 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
34483 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
34484 \ RC5_Compute_3/4_Period: \ |
34485 RRUM #1,X \ X=1/2 cycle |
34489 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
34490 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
34492 \ ------------------------------\
34493 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
34494 \ ------------------------------\
34495 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34496 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
34497 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34498 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34499 SUB #1,W \ decrement count loop
34500 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
34501 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34502 0<> WHILE \ ----> out of loop ----+
34503 \ RC5_compute_7/4_Time_out: \ |
34504 ADD X,Y \ | out of bound = 7/4 period
34505 \ RC5_WaitHalfCycleP1.2_IFG: \ |
34507 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
34508 0>= IF \ | if cycle time out of bound
34509 BIC #$30,&TA0CTL \ | stop timer_A0
34510 RETI \ | then quit to do nothing
34512 \ ------------------------------\ |
34513 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
34515 MOV &TA0R,X \ | | get new RC5_period value
34516 REPEAT \ ----> loop back --+ |
34517 \ ------------------------------\ |
34518 \ RC5_SampleEndOf: \ <---------------------+
34519 \ ------------------------------\
34520 BIC #$30,&TA0CTL \ stop timer_A0
34521 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
34522 \ ******************************\
34523 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34524 \ ******************************\
34525 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
34526 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
34527 XOR IP,X \ (new XOR old) Toggle bit (13)
34528 BIT #BIT13,X \ X(13) = New_RC5_command
34529 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
34531 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
34532 \ ******************************\
34533 \ RC5_ComputeNewRC5word \
34534 \ ******************************\
34536 MOV &BASE,2(PSP) \ save variable BASE before use
34537 MOV TOS,0(PSP) \ save TOS before use
34538 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
34539 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
34540 \ ******************************\
34541 \ RC5_ComputeC6bit \
34542 \ ******************************\
34543 BIT #$4000,IP \ test /C6 bit in IP
34544 0= IF BIS #$40,TOS \ set C6 bit in S
34545 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
34546 \ ******************************\
34547 \ RC5_CommandByteIsDone \ RC5_code --
34548 \ ******************************\
34550 \ ------------------------------\
34551 \ Display IR_RC5 code \
34552 \ ------------------------------\
34553 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
34554 \ ------------------------------\
34555 LO2HI \ switch from assembler to FORTH
34556 ['] LCD_CLEAR IS CR \ redirects CR
34557 ['] LCD_WrC IS EMIT \ redirects EMIT
34558 $10 BASE ! \ change BASE to hexadecimal
34559 CR ." $" 2 U.R \ print IR_RC5 code
34560 ['] (CR) IS CR \ restore CR
34561 ['] (EMIT) IS EMIT \ restore EMIT
34562 HI2LO \ switch from FORTH to assembler
34563 \ ------------------------------\
34564 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
34565 \ ------------------------------\
34566 MOV @PSP+,&BASE \ restore variable BASE
34567 RETI \ CPU is ON, GIE is OFF
34572 \ ------------------------------\
34573 \ TB0CTL = %0000 0010 1001 0100\$3C0
34574 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34575 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34576 \ -- \ID input divider \ 10 = /4
34577 \ -- \MC Mode Control \ 01 = up to TB0CCR0
34578 \ - \TBCLR TimerB Clear
34581 \ --------------------------------\\
34582 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34583 \ -- \CM Capture Mode
34588 \ --- \OUTMOD \ 011 = set/reset
34594 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
34596 \ ------------------------------\
34597 \ set TimerB to make 50kHz PWM \
34598 \ ------------------------------\
34599 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34600 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
34601 \ ------------------------------\
34602 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
34603 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
34604 \ ------------------------------\
34605 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34606 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
34607 \ ------------------------------\
34608 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34609 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
34610 \ ------------------------------\
34611 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
34612 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
34613 \ ------------------------------\
34614 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
34615 \ ------------------------------\
34616 \ set TimerB to generate PWM for LCD_Vo
34617 \ ------------------------------\
34618 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
34619 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
34620 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34621 \ ------------------------------\
34622 BIS.B #LCDVo,&LCDVo_DIR \
34623 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
34624 \ ------------------------------\
34625 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34626 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34627 \ ------------------------------\
34628 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
34629 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
34630 \ ------------------------------\
34631 \ WDT interval init part \
34632 \ ------------------------------\
34633 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
34634 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
34635 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
34636 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
34637 \ ------------------------------\
34639 \ ------------------------------\
34640 BIS.B #RC5,&IR_IE \ enable RC5_Int
34641 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
34642 \ ------------------------------\
34643 \ init interrupt vectors
34644 \ ------------------------------\
34645 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
34646 MOV #RC5_INT,&IR_Vec \ init interrupt vector
34647 \ ------------------------------\
34648 \ define LPM mode for ACCEPT \
34649 \ ------------------------------\
34650 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34651 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34652 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34654 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
34656 \ ------------------------------\
34658 \ ------------------------------\
34659 $03E8 20_US \ 1- wait 20 ms
34660 $03 TOP_LCD \ 2- send DB5=DB4=1
34661 $CD 20_US \ 3- wait 4,1 ms
34662 $03 TOP_LCD \ 4- send again DB5=DB4=1
34663 $5 20_US \ 5- wait 0,1 ms
34664 $03 TOP_LCD \ 6- send again again DB5=DB4=1
34665 $2 20_US \ wait 40 us = LCD cycle
34666 $02 TOP_LCD \ 7- send DB5=1 DB4=0
34667 $2 20_US \ wait 40 us = LCD cycle
34668 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34669 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34670 LCD_Clear \ 10- "LCD_Clear"
34671 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34672 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34673 LCD_Clear \ 10- "LCD_Clear"
34674 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34675 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34677 ['] (CR) IS CR \ ' (CR) is CR
34678 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
34680 ." RC5toLCD is running. Type STOP to quit"
34681 \ NOECHO \ uncomment to run this app without terminal connexion
34682 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
34683 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
34687 : STOP \ stops multitasking, must to be used before downloading app
34688 ['] (WARM) IS WARM \ remove START app from FORTH init process
34689 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
34697 CODE MAX \ n1 n2 -- n3 signed maximum
34698 CMP @PSP,TOS \ n2-n1
34699 S< ?GOTO FW1 \ n2<n1
34705 CODE MIN \ n1 n2 -- n3 signed minimum
34706 CMP @PSP,TOS \ n2-n1
34707 S< ?GOTO BW1 \ n2<n1
34713 : U.R \ u n -- display u unsigned in n width (n >= 2)
34715 R> OVER - 0 MAX SPACES TYPE
34719 CODE 20_US \ n -- n * 20 us
34720 BEGIN \ 3 cycles loop + 6~
34721 \ MOV #5,W \ 3 MCLK = 1 MHz
34722 \ MOV #23,W \ 3 MCLK = 4 MHz
34723 MOV #51,W \ 3 MCLK = 8 MHz
34724 \ MOV #104,W \ 3 MCLK = 16 MHz
34725 \ MOV #158,W \ 3 MCLK = 24 MHz
34726 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
34736 CODE TOP_LCD \ LCD Sample
34737 \ \ if write : %xxxxWWWW --
34738 \ \ if read : -- %0000RRRR
34739 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34740 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34741 0= IF \ write LCD bits pattern
34742 AND.B #LCD_DB,TOS \
34743 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34744 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34747 THEN \ read LCD bits pattern
34750 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34751 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34752 AND.B #LCD_DB,TOS \
34757 CODE LCD_W \ byte -- write byte to LCD
34759 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
34760 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
34761 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34762 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34763 COLON \ high level word starts here
34764 TOP_LCD 2 20_US \ write high nibble first
34769 CODE LCD_WrC \ char -- Write Char
34770 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34775 CODE LCD_WrF \ func -- Write Fonction
34776 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34782 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
34787 $02 LCD_WrF 100 20_us
34791 \ : LCD_Entry_set $04 OR LCD_WrF ;
34793 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
34795 \ : LCD_Display_Shift $10 OR LCD_WrF ;
34797 \ : LCD_Fn_Set $20 OR LCD_WrF ;
34799 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
34801 \ : LCD_Goto $80 OR LCD_WrF ;
34803 \ CODE LCD_R \ -- byte read byte from LCD
34804 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34805 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34806 \ COLON \ starts a FORTH word
34807 \ TOP_LCD 2 20_us \ -- %0000HHHH
34808 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
34809 \ HI2LO \ switch from FORTH to assembler
34810 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
34811 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
34812 \ MOV @RSP+,IP \ restore IP saved by COLON
34817 \ CODE LCD_RdS \ -- status Read Status
34818 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34823 \ CODE LCD_RdC \ -- char Read Char
34824 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34829 \ -------------+------+------+------+------++---+---+---+---+---------+
34830 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
34831 \ -------------+------+------+------+------++---+---+---+---+---------+
34832 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
34833 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
34834 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
34835 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
34836 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
34837 \ -------------+------+------+------+------++---+---+---+---+---------+
34840 \ ******************************\
34841 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34842 \ ******************************\
34843 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
34844 \ ------------------------------\
34845 \ define LPM mode for ACCEPT \
34846 \ ------------------------------\
34847 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34848 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34849 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34850 BIT.B #SW2,&SW2_IN \ test switch S2
34851 0= IF \ case of switch S2 pressed
34852 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
34854 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
34857 BIT.B #SW1,&SW1_IN \ test switch S1 input
34858 0= IF \ case of Switch S1 pressed
34859 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
34861 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
34865 RETI \ CPU is ON, GIE is OFF
34870 \ ------------------------------\
34871 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34872 \ ******************************\
34873 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34874 \ ******************************\
34875 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34876 \ \ SMclock = 8|16|24 MHz
34877 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
34878 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
34879 \ \ SR(9)=new Toggle bit memory (ADD on)
34880 \ ------------------------------\
34881 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
34882 \ ------------------------------\
34883 \ define LPM mode for ACCEPT \
34884 \ ------------------------------\
34885 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34886 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34887 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34888 \ ------------------------------\
34889 \ RC5_FirstStartBitHalfCycle: \
34890 \ ------------------------------\
34891 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
34892 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
34893 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
34894 MOV #1778,X \ RC5_Period in us
34895 MOV #14,W \ count of loop
34897 \ ------------------------------\
34898 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
34899 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
34900 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
34901 \ RC5_Compute_3/4_Period: \ |
34902 RRUM #1,X \ X=1/2 cycle |
34906 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
34907 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
34909 \ ------------------------------\
34910 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
34911 \ ------------------------------\
34912 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34913 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
34914 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34915 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34916 SUB #1,W \ decrement count loop
34917 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
34918 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34919 0<> WHILE \ ----> out of loop ----+
34920 \ RC5_compute_7/4_Time_out: \ |
34921 ADD X,Y \ | out of bound = 7/4 period
34922 \ RC5_WaitHalfCycleP1.2_IFG: \ |
34924 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
34925 0>= IF \ | if cycle time out of bound
34926 BIC #$30,&TA0CTL \ | stop timer_A0
34927 RETI \ | then quit to do nothing
34929 \ ------------------------------\ |
34930 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
34932 MOV &TA0R,X \ | | get new RC5_period value
34933 REPEAT \ ----> loop back --+ |
34934 \ ------------------------------\ |
34935 \ RC5_SampleEndOf: \ <---------------------+
34936 \ ------------------------------\
34937 BIC #$30,&TA0CTL \ stop timer_A0
34938 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
34939 \ ******************************\
34940 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34941 \ ******************************\
34942 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
34943 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
34944 XOR IP,X \ (new XOR old) Toggle bit (13)
34945 BIT #BIT13,X \ X(13) = New_RC5_command
34946 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
34948 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
34949 \ ******************************\
34950 \ RC5_ComputeNewRC5word \
34951 \ ******************************\
34953 MOV &BASE,2(PSP) \ save variable BASE before use
34954 MOV TOS,0(PSP) \ save TOS before use
34955 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
34956 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
34957 \ ******************************\
34958 \ RC5_ComputeC6bit \
34959 \ ******************************\
34960 BIT #$4000,IP \ test /C6 bit in IP
34961 0= IF BIS #$40,TOS \ set C6 bit in S
34962 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
34963 \ ******************************\
34964 \ RC5_CommandByteIsDone \ RC5_code --
34965 \ ******************************\
34967 \ ------------------------------\
34968 \ Display IR_RC5 code \
34969 \ ------------------------------\
34970 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
34971 \ ------------------------------\
34972 LO2HI \ switch from assembler to FORTH
34973 ['] LCD_CLEAR IS CR \ redirects CR
34974 ['] LCD_WrC IS EMIT \ redirects EMIT
34975 $10 BASE ! \ change BASE to hexadecimal
34976 CR ." $" 2 U.R \ print IR_RC5 code
34977 ['] (CR) IS CR \ restore CR
34978 ['] (EMIT) IS EMIT \ restore EMIT
34979 HI2LO \ switch from FORTH to assembler
34980 \ ------------------------------\
34981 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
34982 \ ------------------------------\
34983 MOV @PSP+,&BASE \ restore variable BASE
34984 RETI \ CPU is ON, GIE is OFF
34989 \ ------------------------------\
34990 \ TB0CTL = %0000 0010 1001 0100\$3C0
34991 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34992 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34993 \ -- \ID input divider \ 10 = /4
34994 \ -- \MC Mode Control \ 01 = up to TB0CCR0
34995 \ - \TBCLR TimerB Clear
34998 \ --------------------------------\\
34999 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35000 \ -- \CM Capture Mode
35005 \ --- \OUTMOD \ 011 = set/reset
35011 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
35013 \ ------------------------------\
35014 \ set TimerB to make 50kHz PWM \
35015 \ ------------------------------\
35016 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35017 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
35018 \ ------------------------------\
35019 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35020 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
35021 \ ------------------------------\
35022 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35023 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
35024 \ ------------------------------\
35025 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35026 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
35027 \ ------------------------------\
35028 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35029 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
35030 \ ------------------------------\
35031 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
35032 \ ------------------------------\
35033 \ set TimerB to generate PWM for LCD_Vo
35034 \ ------------------------------\
35035 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
35036 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
35037 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35038 \ ------------------------------\
35039 BIS.B #LCDVo,&LCDVo_DIR \
35040 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
35041 \ ------------------------------\
35042 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35043 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35044 \ ------------------------------\
35045 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35046 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35047 \ ------------------------------\
35048 \ WDT interval init part \
35049 \ ------------------------------\
35050 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
35051 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
35052 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
35053 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
35054 \ ------------------------------\
35056 \ ------------------------------\
35057 BIS.B #RC5,&IR_IE \ enable RC5_Int
35058 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35059 \ ------------------------------\
35060 \ init interrupt vectors
35061 \ ------------------------------\
35062 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
35063 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35064 \ ------------------------------\
35065 \ define LPM mode for ACCEPT \
35066 \ ------------------------------\
35067 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35068 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35069 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35071 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
35073 \ ------------------------------\
35075 \ ------------------------------\
35076 $03E8 20_US \ 1- wait 20 ms
35077 $03 TOP_LCD \ 2- send DB5=DB4=1
35078 $CD 20_US \ 3- wait 4,1 ms
35079 $03 TOP_LCD \ 4- send again DB5=DB4=1
35080 $5 20_US \ 5- wait 0,1 ms
35081 $03 TOP_LCD \ 6- send again again DB5=DB4=1
35082 $2 20_US \ wait 40 us = LCD cycle
35083 $02 TOP_LCD \ 7- send DB5=1 DB4=0
35084 $2 20_US \ wait 40 us = LCD cycle
35085 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35086 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35087 LCD_Clear \ 10- "LCD_Clear"
35088 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35089 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35090 LCD_Clear \ 10- "LCD_Clear"
35091 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35092 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35094 ['] (CR) IS CR \ ' (CR) is CR
35095 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
35097 ." RC5toLCD is running. Type STOP to quit"
35098 \ NOECHO \ uncomment to run this app without terminal connexion
35099 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
35100 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
35104 : STOP \ stops multitasking, must to be used before downloading app
35105 ['] (WARM) IS WARM \ remove START app from FORTH init process
35106 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
35114 CODE MAX \ n1 n2 -- n3 signed maximum
35115 CMP @PSP,TOS \ n2-n1
35116 S< ?GOTO FW1 \ n2<n1
35122 CODE MIN \ n1 n2 -- n3 signed minimum
35123 CMP @PSP,TOS \ n2-n1
35124 S< ?GOTO BW1 \ n2<n1
35130 : U.R \ u n -- display u unsigned in n width (n >= 2)
35132 R> OVER - 0 MAX SPACES TYPE
35136 CODE 20_US \ n -- n * 20 us
35137 BEGIN \ 3 cycles loop + 6~
35138 \ MOV #5,W \ 3 MCLK = 1 MHz
35139 \ MOV #23,W \ 3 MCLK = 4 MHz
35140 MOV #51,W \ 3 MCLK = 8 MHz
35141 \ MOV #104,W \ 3 MCLK = 16 MHz
35142 \ MOV #158,W \ 3 MCLK = 24 MHz
35143 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
35153 CODE TOP_LCD \ LCD Sample
35154 \ \ if write : %xxxxWWWW --
35155 \ \ if read : -- %0000RRRR
35156 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35157 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35158 0= IF \ write LCD bits pattern
35159 AND.B #LCD_DB,TOS \
35160 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35161 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35164 THEN \ read LCD bits pattern
35167 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35168 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35169 AND.B #LCD_DB,TOS \
35174 CODE LCD_W \ byte -- write byte to LCD
35176 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
35177 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
35178 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35179 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35180 COLON \ high level word starts here
35181 TOP_LCD 2 20_US \ write high nibble first
35186 CODE LCD_WrC \ char -- Write Char
35187 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35192 CODE LCD_WrF \ func -- Write Fonction
35193 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35199 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
35204 $02 LCD_WrF 100 20_us
35208 \ : LCD_Entry_set $04 OR LCD_WrF ;
35210 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
35212 \ : LCD_Display_Shift $10 OR LCD_WrF ;
35214 \ : LCD_Fn_Set $20 OR LCD_WrF ;
35216 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
35218 \ : LCD_Goto $80 OR LCD_WrF ;
35220 \ CODE LCD_R \ -- byte read byte from LCD
35221 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35222 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35223 \ COLON \ starts a FORTH word
35224 \ TOP_LCD 2 20_us \ -- %0000HHHH
35225 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
35226 \ HI2LO \ switch from FORTH to assembler
35227 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
35228 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
35229 \ MOV @RSP+,IP \ restore IP saved by COLON
35234 \ CODE LCD_RdS \ -- status Read Status
35235 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35240 \ CODE LCD_RdC \ -- char Read Char
35241 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35246 \ -------------+------+------+------+------++---+---+---+---+---------+
35247 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
35248 \ -------------+------+------+------+------++---+---+---+---+---------+
35249 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
35250 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
35251 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
35252 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
35253 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
35254 \ -------------+------+------+------+------++---+---+---+---+---------+
35257 \ ******************************\
35258 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35259 \ ******************************\
35260 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
35261 \ ------------------------------\
35262 \ define LPM mode for ACCEPT \
35263 \ ------------------------------\
35264 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35265 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35266 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35267 BIT.B #SW2,&SW2_IN \ test switch S2
35268 0= IF \ case of switch S2 pressed
35269 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
35271 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
35274 BIT.B #SW1,&SW1_IN \ test switch S1 input
35275 0= IF \ case of Switch S1 pressed
35276 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
35278 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
35282 RETI \ CPU is ON, GIE is OFF
35287 \ ------------------------------\
35288 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35289 \ ******************************\
35290 ASM RC5_INT \ wake up on Px.RC5 change interrupt
35291 \ ******************************\
35292 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35293 \ \ SMclock = 8|16|24 MHz
35294 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
35295 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
35296 \ \ SR(9)=new Toggle bit memory (ADD on)
35297 \ ------------------------------\
35298 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
35299 \ ------------------------------\
35300 \ define LPM mode for ACCEPT \
35301 \ ------------------------------\
35302 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35303 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35304 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35305 \ ------------------------------\
35306 \ RC5_FirstStartBitHalfCycle: \
35307 \ ------------------------------\
35308 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
35309 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
35310 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
35311 MOV #1778,X \ RC5_Period in us
35312 MOV #14,W \ count of loop
35314 \ ------------------------------\
35315 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
35316 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
35317 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
35318 \ RC5_Compute_3/4_Period: \ |
35319 RRUM #1,X \ X=1/2 cycle |
35323 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
35324 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
35326 \ ------------------------------\
35327 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
35328 \ ------------------------------\
35329 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35330 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
35331 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35332 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35333 SUB #1,W \ decrement count loop
35334 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
35335 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35336 0<> WHILE \ ----> out of loop ----+
35337 \ RC5_compute_7/4_Time_out: \ |
35338 ADD X,Y \ | out of bound = 7/4 period
35339 \ RC5_WaitHalfCycleP1.2_IFG: \ |
35341 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
35342 0>= IF \ | if cycle time out of bound
35343 BIC #$30,&TA0CTL \ | stop timer_A0
35344 RETI \ | then quit to do nothing
35346 \ ------------------------------\ |
35347 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
35349 MOV &TA0R,X \ | | get new RC5_period value
35350 REPEAT \ ----> loop back --+ |
35351 \ ------------------------------\ |
35352 \ RC5_SampleEndOf: \ <---------------------+
35353 \ ------------------------------\
35354 BIC #$30,&TA0CTL \ stop timer_A0
35355 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
35356 \ ******************************\
35357 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
35358 \ ******************************\
35359 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
35360 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
35361 XOR IP,X \ (new XOR old) Toggle bit (13)
35362 BIT #BIT13,X \ X(13) = New_RC5_command
35363 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
35365 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
35366 \ ******************************\
35367 \ RC5_ComputeNewRC5word \
35368 \ ******************************\
35370 MOV &BASE,2(PSP) \ save variable BASE before use
35371 MOV TOS,0(PSP) \ save TOS before use
35372 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
35373 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
35374 \ ******************************\
35375 \ RC5_ComputeC6bit \
35376 \ ******************************\
35377 BIT #$4000,IP \ test /C6 bit in IP
35378 0= IF BIS #$40,TOS \ set C6 bit in S
35379 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
35380 \ ******************************\
35381 \ RC5_CommandByteIsDone \ RC5_code --
35382 \ ******************************\
35384 \ ------------------------------\
35385 \ Display IR_RC5 code \
35386 \ ------------------------------\
35387 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
35388 \ ------------------------------\
35389 LO2HI \ switch from assembler to FORTH
35390 ['] LCD_CLEAR IS CR \ redirects CR
35391 ['] LCD_WrC IS EMIT \ redirects EMIT
35392 $10 BASE ! \ change BASE to hexadecimal
35393 CR ." $" 2 U.R \ print IR_RC5 code
35394 ['] (CR) IS CR \ restore CR
35395 ['] (EMIT) IS EMIT \ restore EMIT
35396 HI2LO \ switch from FORTH to assembler
35397 \ ------------------------------\
35398 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
35399 \ ------------------------------\
35400 MOV @PSP+,&BASE \ restore variable BASE
35401 RETI \ CPU is ON, GIE is OFF
35406 \ ------------------------------\
35407 \ TB0CTL = %0000 0010 1001 0100\$3C0
35408 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35409 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35410 \ -- \ID input divider \ 10 = /4
35411 \ -- \MC Mode Control \ 01 = up to TB0CCR0
35412 \ - \TBCLR TimerB Clear
35415 \ --------------------------------\\
35416 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35417 \ -- \CM Capture Mode
35422 \ --- \OUTMOD \ 011 = set/reset
35428 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
35430 \ ------------------------------\
35431 \ set TimerB to make 50kHz PWM \
35432 \ ------------------------------\
35433 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35434 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
35435 \ ------------------------------\
35436 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35437 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
35438 \ ------------------------------\
35439 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35440 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
35441 \ ------------------------------\
35442 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35443 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
35444 \ ------------------------------\
35445 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35446 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
35447 \ ------------------------------\
35448 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
35449 \ ------------------------------\
35450 \ set TimerB to generate PWM for LCD_Vo
35451 \ ------------------------------\
35452 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
35453 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
35454 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35455 \ ------------------------------\
35456 BIS.B #LCDVo,&LCDVo_DIR \
35457 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
35458 \ ------------------------------\
35459 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35460 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35461 \ ------------------------------\
35462 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35463 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35464 \ ------------------------------\
35465 \ WDT interval init part \
35466 \ ------------------------------\
35467 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
35468 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
35469 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
35470 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
35471 \ ------------------------------\
35473 \ ------------------------------\
35474 BIS.B #RC5,&IR_IE \ enable RC5_Int
35475 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35476 \ ------------------------------\
35477 \ init interrupt vectors
35478 \ ------------------------------\
35479 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
35480 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35481 \ ------------------------------\
35482 \ define LPM mode for ACCEPT \
35483 \ ------------------------------\
35484 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35485 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35486 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35488 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
35490 \ ------------------------------\
35492 \ ------------------------------\
35493 $03E8 20_US \ 1- wait 20 ms
35494 $03 TOP_LCD \ 2- send DB5=DB4=1
35495 $CD 20_US \ 3- wait 4,1 ms
35496 $03 TOP_LCD \ 4- send again DB5=DB4=1
35497 $5 20_US \ 5- wait 0,1 ms
35498 $03 TOP_LCD \ 6- send again again DB5=DB4=1
35499 $2 20_US \ wait 40 us = LCD cycle
35500 $02 TOP_LCD \ 7- send DB5=1 DB4=0
35501 $2 20_US \ wait 40 us = LCD cycle
35502 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35503 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35504 LCD_Clear \ 10- "LCD_Clear"
35505 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35506 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35507 LCD_Clear \ 10- "LCD_Clear"
35508 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35509 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35511 ['] (CR) IS CR \ ' (CR) is CR
35512 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
35514 ." RC5toLCD is running. Type STOP to quit"
35515 \ NOECHO \ uncomment to run this app without terminal connexion
35516 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
35517 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
35521 : STOP \ stops multitasking, must to be used before downloading app
35522 ['] (WARM) IS WARM \ remove START app from FORTH init process
35523 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
35531 CODE MAX \ n1 n2 -- n3 signed maximum
35532 CMP @PSP,TOS \ n2-n1
35533 S< ?GOTO FW1 \ n2<n1
35539 CODE MIN \ n1 n2 -- n3 signed minimum
35540 CMP @PSP,TOS \ n2-n1
35541 S< ?GOTO BW1 \ n2<n1
35547 : U.R \ u n -- display u unsigned in n width (n >= 2)
35549 R> OVER - 0 MAX SPACES TYPE
35553 CODE 20_US \ n -- n * 20 us
35554 BEGIN \ 3 cycles loop + 6~
35555 \ MOV #5,W \ 3 MCLK = 1 MHz
35556 \ MOV #23,W \ 3 MCLK = 4 MHz
35557 MOV #51,W \ 3 MCLK = 8 MHz
35558 \ MOV #104,W \ 3 MCLK = 16 MHz
35559 \ MOV #158,W \ 3 MCLK = 24 MHz
35560 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
35570 CODE TOP_LCD \ LCD Sample
35571 \ \ if write : %xxxxWWWW --
35572 \ \ if read : -- %0000RRRR
35573 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35574 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35575 0= IF \ write LCD bits pattern
35576 AND.B #LCD_DB,TOS \
35577 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35578 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35581 THEN \ read LCD bits pattern
35584 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35585 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35586 AND.B #LCD_DB,TOS \
35591 CODE LCD_W \ byte -- write byte to LCD
35593 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
35594 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
35595 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35596 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35597 COLON \ high level word starts here
35598 TOP_LCD 2 20_US \ write high nibble first
35603 CODE LCD_WrC \ char -- Write Char
35604 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35609 CODE LCD_WrF \ func -- Write Fonction
35610 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35616 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
35621 $02 LCD_WrF 100 20_us
35625 \ : LCD_Entry_set $04 OR LCD_WrF ;
35627 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
35629 \ : LCD_Display_Shift $10 OR LCD_WrF ;
35631 \ : LCD_Fn_Set $20 OR LCD_WrF ;
35633 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
35635 \ : LCD_Goto $80 OR LCD_WrF ;
35637 \ CODE LCD_R \ -- byte read byte from LCD
35638 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35639 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35640 \ COLON \ starts a FORTH word
35641 \ TOP_LCD 2 20_us \ -- %0000HHHH
35642 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
35643 \ HI2LO \ switch from FORTH to assembler
35644 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
35645 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
35646 \ MOV @RSP+,IP \ restore IP saved by COLON
35651 \ CODE LCD_RdS \ -- status Read Status
35652 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35657 \ CODE LCD_RdC \ -- char Read Char
35658 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35663 \ -------------+------+------+------+------++---+---+---+---+---------+
35664 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
35665 \ -------------+------+------+------+------++---+---+---+---+---------+
35666 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
35667 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
35668 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
35669 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
35670 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
35671 \ -------------+------+------+------+------++---+---+---+---+---------+
35674 \ ******************************\
35675 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35676 \ ******************************\
35677 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
35678 \ ------------------------------\
35679 \ define LPM mode for ACCEPT \
35680 \ ------------------------------\
35681 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35682 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35683 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35684 BIT.B #SW2,&SW2_IN \ test switch S2
35685 0= IF \ case of switch S2 pressed
35686 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
35688 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
35691 BIT.B #SW1,&SW1_IN \ test switch S1 input
35692 0= IF \ case of Switch S1 pressed
35693 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
35695 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
35699 RETI \ CPU is ON, GIE is OFF
35704 \ ------------------------------\
35705 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35706 \ ******************************\
35707 ASM RC5_INT \ wake up on Px.RC5 change interrupt
35708 \ ******************************\
35709 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35710 \ \ SMclock = 8|16|24 MHz
35711 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
35712 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
35713 \ \ SR(9)=new Toggle bit memory (ADD on)
35714 \ ------------------------------\
35715 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
35716 \ ------------------------------\
35717 \ define LPM mode for ACCEPT \
35718 \ ------------------------------\
35719 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35720 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35721 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35722 \ ------------------------------\
35723 \ RC5_FirstStartBitHalfCycle: \
35724 \ ------------------------------\
35725 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
35726 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
35727 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
35728 MOV #1778,X \ RC5_Period in us
35729 MOV #14,W \ count of loop
35731 \ ------------------------------\
35732 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
35733 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
35734 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
35735 \ RC5_Compute_3/4_Period: \ |
35736 RRUM #1,X \ X=1/2 cycle |
35740 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
35741 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
35743 \ ------------------------------\
35744 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
35745 \ ------------------------------\
35746 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35747 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
35748 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35749 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35750 SUB #1,W \ decrement count loop
35751 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
35752 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35753 0<> WHILE \ ----> out of loop ----+
35754 \ RC5_compute_7/4_Time_out: \ |
35755 ADD X,Y \ | out of bound = 7/4 period
35756 \ RC5_WaitHalfCycleP1.2_IFG: \ |
35758 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
35759 0>= IF \ | if cycle time out of bound
35760 BIC #$30,&TA0CTL \ | stop timer_A0
35761 RETI \ | then quit to do nothing
35763 \ ------------------------------\ |
35764 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
35766 MOV &TA0R,X \ | | get new RC5_period value
35767 REPEAT \ ----> loop back --+ |
35768 \ ------------------------------\ |
35769 \ RC5_SampleEndOf: \ <---------------------+
35770 \ ------------------------------\
35771 BIC #$30,&TA0CTL \ stop timer_A0
35772 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
35773 \ ******************************\
35774 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
35775 \ ******************************\
35776 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
35777 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
35778 XOR IP,X \ (new XOR old) Toggle bit (13)
35779 BIT #BIT13,X \ X(13) = New_RC5_command
35780 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
35782 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
35783 \ ******************************\
35784 \ RC5_ComputeNewRC5word \
35785 \ ******************************\
35787 MOV &BASE,2(PSP) \ save variable BASE before use
35788 MOV TOS,0(PSP) \ save TOS before use
35789 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
35790 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
35791 \ ******************************\
35792 \ RC5_ComputeC6bit \
35793 \ ******************************\
35794 BIT #$4000,IP \ test /C6 bit in IP
35795 0= IF BIS #$40,TOS \ set C6 bit in S
35796 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
35797 \ ******************************\
35798 \ RC5_CommandByteIsDone \ RC5_code --
35799 \ ******************************\
35801 \ ------------------------------\
35802 \ Display IR_RC5 code \
35803 \ ------------------------------\
35804 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
35805 \ ------------------------------\
35806 LO2HI \ switch from assembler to FORTH
35807 ['] LCD_CLEAR IS CR \ redirects CR
35808 ['] LCD_WrC IS EMIT \ redirects EMIT
35809 $10 BASE ! \ change BASE to hexadecimal
35810 CR ." $" 2 U.R \ print IR_RC5 code
35811 ['] (CR) IS CR \ restore CR
35812 ['] (EMIT) IS EMIT \ restore EMIT
35813 HI2LO \ switch from FORTH to assembler
35814 \ ------------------------------\
35815 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
35816 \ ------------------------------\
35817 MOV @PSP+,&BASE \ restore variable BASE
35818 RETI \ CPU is ON, GIE is OFF
35823 \ ------------------------------\
35824 \ TB0CTL = %0000 0010 1001 0100\$3C0
35825 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35826 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35827 \ -- \ID input divider \ 10 = /4
35828 \ -- \MC Mode Control \ 01 = up to TB0CCR0
35829 \ - \TBCLR TimerB Clear
35832 \ --------------------------------\\
35833 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35834 \ -- \CM Capture Mode
35839 \ --- \OUTMOD \ 011 = set/reset
35845 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
35847 \ ------------------------------\
35848 \ set TimerB to make 50kHz PWM \
35849 \ ------------------------------\
35850 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35851 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
35852 \ ------------------------------\
35853 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
35854 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
35855 \ ------------------------------\
35856 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35857 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
35858 \ ------------------------------\
35859 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35860 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
35861 \ ------------------------------\
35862 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
35863 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
35864 \ ------------------------------\
35865 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
35866 \ ------------------------------\
35867 \ set TimerB to generate PWM for LCD_Vo
35868 \ ------------------------------\
35869 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
35870 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
35871 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35872 \ ------------------------------\
35873 BIS.B #LCDVo,&LCDVo_DIR \
35874 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
35875 \ ------------------------------\
35876 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35877 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35878 \ ------------------------------\
35879 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35880 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35881 \ ------------------------------\
35882 \ WDT interval init part \
35883 \ ------------------------------\
35884 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
35885 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
35886 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
35887 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
35888 \ ------------------------------\
35890 \ ------------------------------\
35891 BIS.B #RC5,&IR_IE \ enable RC5_Int
35892 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35893 \ ------------------------------\
35894 \ init interrupt vectors
35895 \ ------------------------------\
35896 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
35897 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35898 \ ------------------------------\
35899 \ define LPM mode for ACCEPT \
35900 \ ------------------------------\
35901 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35902 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35903 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35905 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
35907 \ ------------------------------\
35909 \ ------------------------------\
35910 $03E8 20_US \ 1- wait 20 ms
35911 $03 TOP_LCD \ 2- send DB5=DB4=1
35912 $CD 20_US \ 3- wait 4,1 ms
35913 $03 TOP_LCD \ 4- send again DB5=DB4=1
35914 $5 20_US \ 5- wait 0,1 ms
35915 $03 TOP_LCD \ 6- send again again DB5=DB4=1
35916 $2 20_US \ wait 40 us = LCD cycle
35917 $02 TOP_LCD \ 7- send DB5=1 DB4=0
35918 $2 20_US \ wait 40 us = LCD cycle
35919 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35920 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35921 LCD_Clear \ 10- "LCD_Clear"
35922 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35923 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35924 LCD_Clear \ 10- "LCD_Clear"
35925 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35926 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35928 ['] (CR) IS CR \ ' (CR) is CR
35929 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
35931 ." RC5toLCD is running. Type STOP to quit"
35932 \ NOECHO \ uncomment to run this app without terminal connexion
35933 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
35934 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
35938 : STOP \ stops multitasking, must to be used before downloading app
35939 ['] (WARM) IS WARM \ remove START app from FORTH init process
35940 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
35948 CODE MAX \ n1 n2 -- n3 signed maximum
35949 CMP @PSP,TOS \ n2-n1
35950 S< ?GOTO FW1 \ n2<n1
35956 CODE MIN \ n1 n2 -- n3 signed minimum
35957 CMP @PSP,TOS \ n2-n1
35958 S< ?GOTO BW1 \ n2<n1
35964 : U.R \ u n -- display u unsigned in n width (n >= 2)
35966 R> OVER - 0 MAX SPACES TYPE
35970 CODE 20_US \ n -- n * 20 us
35971 BEGIN \ 3 cycles loop + 6~
35972 \ MOV #5,W \ 3 MCLK = 1 MHz
35973 \ MOV #23,W \ 3 MCLK = 4 MHz
35974 MOV #51,W \ 3 MCLK = 8 MHz
35975 \ MOV #104,W \ 3 MCLK = 16 MHz
35976 \ MOV #158,W \ 3 MCLK = 24 MHz
35977 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
35987 CODE TOP_LCD \ LCD Sample
35988 \ \ if write : %xxxxWWWW --
35989 \ \ if read : -- %0000RRRR
35990 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35991 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35992 0= IF \ write LCD bits pattern
35993 AND.B #LCD_DB,TOS \
35994 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35995 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35998 THEN \ read LCD bits pattern
36001 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36002 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36003 AND.B #LCD_DB,TOS \
36008 CODE LCD_W \ byte -- write byte to LCD
36010 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
36011 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
36012 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36013 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36014 COLON \ high level word starts here
36015 TOP_LCD 2 20_US \ write high nibble first
36020 CODE LCD_WrC \ char -- Write Char
36021 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36026 CODE LCD_WrF \ func -- Write Fonction
36027 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36033 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
36038 $02 LCD_WrF 100 20_us
36042 \ : LCD_Entry_set $04 OR LCD_WrF ;
36044 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
36046 \ : LCD_Display_Shift $10 OR LCD_WrF ;
36048 \ : LCD_Fn_Set $20 OR LCD_WrF ;
36050 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
36052 \ : LCD_Goto $80 OR LCD_WrF ;
36054 \ CODE LCD_R \ -- byte read byte from LCD
36055 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36056 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36057 \ COLON \ starts a FORTH word
36058 \ TOP_LCD 2 20_us \ -- %0000HHHH
36059 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
36060 \ HI2LO \ switch from FORTH to assembler
36061 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
36062 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
36063 \ MOV @RSP+,IP \ restore IP saved by COLON
36068 \ CODE LCD_RdS \ -- status Read Status
36069 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36074 \ CODE LCD_RdC \ -- char Read Char
36075 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36080 \ -------------+------+------+------+------++---+---+---+---+---------+
36081 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
36082 \ -------------+------+------+------+------++---+---+---+---+---------+
36083 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
36084 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
36085 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
36086 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
36087 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
36088 \ -------------+------+------+------+------++---+---+---+---+---------+
36091 \ ******************************\
36092 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36093 \ ******************************\
36094 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
36095 \ ------------------------------\
36096 \ define LPM mode for ACCEPT \
36097 \ ------------------------------\
36098 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36099 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36100 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36101 BIT.B #SW2,&SW2_IN \ test switch S2
36102 0= IF \ case of switch S2 pressed
36103 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
36105 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
36108 BIT.B #SW1,&SW1_IN \ test switch S1 input
36109 0= IF \ case of Switch S1 pressed
36110 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
36112 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
36116 RETI \ CPU is ON, GIE is OFF
36121 \ ------------------------------\
36122 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36123 \ ******************************\
36124 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36125 \ ******************************\
36126 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36127 \ \ SMclock = 8|16|24 MHz
36128 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
36129 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
36130 \ \ SR(9)=new Toggle bit memory (ADD on)
36131 \ ------------------------------\
36132 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
36133 \ ------------------------------\
36134 \ define LPM mode for ACCEPT \
36135 \ ------------------------------\
36136 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36137 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36138 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36139 \ ------------------------------\
36140 \ RC5_FirstStartBitHalfCycle: \
36141 \ ------------------------------\
36142 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
36143 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
36144 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
36145 MOV #1778,X \ RC5_Period in us
36146 MOV #14,W \ count of loop
36148 \ ------------------------------\
36149 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
36150 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
36151 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
36152 \ RC5_Compute_3/4_Period: \ |
36153 RRUM #1,X \ X=1/2 cycle |
36157 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
36158 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
36160 \ ------------------------------\
36161 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
36162 \ ------------------------------\
36163 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36164 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
36165 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36166 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36167 SUB #1,W \ decrement count loop
36168 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
36169 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36170 0<> WHILE \ ----> out of loop ----+
36171 \ RC5_compute_7/4_Time_out: \ |
36172 ADD X,Y \ | out of bound = 7/4 period
36173 \ RC5_WaitHalfCycleP1.2_IFG: \ |
36175 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
36176 0>= IF \ | if cycle time out of bound
36177 BIC #$30,&TA0CTL \ | stop timer_A0
36178 RETI \ | then quit to do nothing
36180 \ ------------------------------\ |
36181 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
36183 MOV &TA0R,X \ | | get new RC5_period value
36184 REPEAT \ ----> loop back --+ |
36185 \ ------------------------------\ |
36186 \ RC5_SampleEndOf: \ <---------------------+
36187 \ ------------------------------\
36188 BIC #$30,&TA0CTL \ stop timer_A0
36189 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
36190 \ ******************************\
36191 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
36192 \ ******************************\
36193 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
36194 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
36195 XOR IP,X \ (new XOR old) Toggle bit (13)
36196 BIT #BIT13,X \ X(13) = New_RC5_command
36197 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
36199 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
36200 \ ******************************\
36201 \ RC5_ComputeNewRC5word \
36202 \ ******************************\
36204 MOV &BASE,2(PSP) \ save variable BASE before use
36205 MOV TOS,0(PSP) \ save TOS before use
36206 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
36207 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
36208 \ ******************************\
36209 \ RC5_ComputeC6bit \
36210 \ ******************************\
36211 BIT #$4000,IP \ test /C6 bit in IP
36212 0= IF BIS #$40,TOS \ set C6 bit in S
36213 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
36214 \ ******************************\
36215 \ RC5_CommandByteIsDone \ RC5_code --
36216 \ ******************************\
36218 \ ------------------------------\
36219 \ Display IR_RC5 code \
36220 \ ------------------------------\
36221 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
36222 \ ------------------------------\
36223 LO2HI \ switch from assembler to FORTH
36224 ['] LCD_CLEAR IS CR \ redirects CR
36225 ['] LCD_WrC IS EMIT \ redirects EMIT
36226 $10 BASE ! \ change BASE to hexadecimal
36227 CR ." $" 2 U.R \ print IR_RC5 code
36228 ['] (CR) IS CR \ restore CR
36229 ['] (EMIT) IS EMIT \ restore EMIT
36230 HI2LO \ switch from FORTH to assembler
36231 \ ------------------------------\
36232 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
36233 \ ------------------------------\
36234 MOV @PSP+,&BASE \ restore variable BASE
36235 RETI \ CPU is ON, GIE is OFF
36240 \ ------------------------------\
36241 \ TB0CTL = %0000 0010 1001 0100\$3C0
36242 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36243 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36244 \ -- \ID input divider \ 10 = /4
36245 \ -- \MC Mode Control \ 01 = up to TB0CCR0
36246 \ - \TBCLR TimerB Clear
36249 \ --------------------------------\\
36250 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36251 \ -- \CM Capture Mode
36256 \ --- \OUTMOD \ 011 = set/reset
36262 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
36264 \ ------------------------------\
36265 \ set TimerB to make 50kHz PWM \
36266 \ ------------------------------\
36267 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36268 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
36269 \ ------------------------------\
36270 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36271 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
36272 \ ------------------------------\
36273 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36274 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
36275 \ ------------------------------\
36276 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36277 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
36278 \ ------------------------------\
36279 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36280 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
36281 \ ------------------------------\
36282 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
36283 \ ------------------------------\
36284 \ set TimerB to generate PWM for LCD_Vo
36285 \ ------------------------------\
36286 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
36287 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
36288 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36289 \ ------------------------------\
36290 BIS.B #LCDVo,&LCDVo_DIR \
36291 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
36292 \ ------------------------------\
36293 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36294 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36295 \ ------------------------------\
36296 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36297 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36298 \ ------------------------------\
36299 \ WDT interval init part \
36300 \ ------------------------------\
36301 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
36302 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
36303 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
36304 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
36305 \ ------------------------------\
36307 \ ------------------------------\
36308 BIS.B #RC5,&IR_IE \ enable RC5_Int
36309 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36310 \ ------------------------------\
36311 \ init interrupt vectors
36312 \ ------------------------------\
36313 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
36314 MOV #RC5_INT,&IR_Vec \ init interrupt vector
36315 \ ------------------------------\
36316 \ define LPM mode for ACCEPT \
36317 \ ------------------------------\
36318 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36319 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36320 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36322 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
36324 \ ------------------------------\
36326 \ ------------------------------\
36327 $03E8 20_US \ 1- wait 20 ms
36328 $03 TOP_LCD \ 2- send DB5=DB4=1
36329 $CD 20_US \ 3- wait 4,1 ms
36330 $03 TOP_LCD \ 4- send again DB5=DB4=1
36331 $5 20_US \ 5- wait 0,1 ms
36332 $03 TOP_LCD \ 6- send again again DB5=DB4=1
36333 $2 20_US \ wait 40 us = LCD cycle
36334 $02 TOP_LCD \ 7- send DB5=1 DB4=0
36335 $2 20_US \ wait 40 us = LCD cycle
36336 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36337 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36338 LCD_Clear \ 10- "LCD_Clear"
36339 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36340 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36341 LCD_Clear \ 10- "LCD_Clear"
36342 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36343 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36345 ['] (CR) IS CR \ ' (CR) is CR
36346 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
36348 ." RC5toLCD is running. Type STOP to quit"
36349 \ NOECHO \ uncomment to run this app without terminal connexion
36350 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
36351 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
36355 : STOP \ stops multitasking, must to be used before downloading app
36356 ['] (WARM) IS WARM \ remove START app from FORTH init process
36357 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
36365 CODE MAX \ n1 n2 -- n3 signed maximum
36366 CMP @PSP,TOS \ n2-n1
36367 S< ?GOTO FW1 \ n2<n1
36373 CODE MIN \ n1 n2 -- n3 signed minimum
36374 CMP @PSP,TOS \ n2-n1
36375 S< ?GOTO BW1 \ n2<n1
36381 : U.R \ u n -- display u unsigned in n width (n >= 2)
36383 R> OVER - 0 MAX SPACES TYPE
36387 CODE 20_US \ n -- n * 20 us
36388 BEGIN \ 3 cycles loop + 6~
36389 \ MOV #5,W \ 3 MCLK = 1 MHz
36390 \ MOV #23,W \ 3 MCLK = 4 MHz
36391 MOV #51,W \ 3 MCLK = 8 MHz
36392 \ MOV #104,W \ 3 MCLK = 16 MHz
36393 \ MOV #158,W \ 3 MCLK = 24 MHz
36394 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
36404 CODE TOP_LCD \ LCD Sample
36405 \ \ if write : %xxxxWWWW --
36406 \ \ if read : -- %0000RRRR
36407 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36408 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36409 0= IF \ write LCD bits pattern
36410 AND.B #LCD_DB,TOS \
36411 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36412 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36415 THEN \ read LCD bits pattern
36418 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36419 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36420 AND.B #LCD_DB,TOS \
36425 CODE LCD_W \ byte -- write byte to LCD
36427 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
36428 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
36429 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36430 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36431 COLON \ high level word starts here
36432 TOP_LCD 2 20_US \ write high nibble first
36437 CODE LCD_WrC \ char -- Write Char
36438 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36443 CODE LCD_WrF \ func -- Write Fonction
36444 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36450 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
36455 $02 LCD_WrF 100 20_us
36459 \ : LCD_Entry_set $04 OR LCD_WrF ;
36461 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
36463 \ : LCD_Display_Shift $10 OR LCD_WrF ;
36465 \ : LCD_Fn_Set $20 OR LCD_WrF ;
36467 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
36469 \ : LCD_Goto $80 OR LCD_WrF ;
36471 \ CODE LCD_R \ -- byte read byte from LCD
36472 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36473 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36474 \ COLON \ starts a FORTH word
36475 \ TOP_LCD 2 20_us \ -- %0000HHHH
36476 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
36477 \ HI2LO \ switch from FORTH to assembler
36478 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
36479 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
36480 \ MOV @RSP+,IP \ restore IP saved by COLON
36485 \ CODE LCD_RdS \ -- status Read Status
36486 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36491 \ CODE LCD_RdC \ -- char Read Char
36492 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36497 \ -------------+------+------+------+------++---+---+---+---+---------+
36498 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
36499 \ -------------+------+------+------+------++---+---+---+---+---------+
36500 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
36501 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
36502 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
36503 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
36504 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
36505 \ -------------+------+------+------+------++---+---+---+---+---------+
36508 \ ******************************\
36509 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36510 \ ******************************\
36511 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
36512 \ ------------------------------\
36513 \ define LPM mode for ACCEPT \
36514 \ ------------------------------\
36515 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36516 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36517 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36518 BIT.B #SW2,&SW2_IN \ test switch S2
36519 0= IF \ case of switch S2 pressed
36520 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
36522 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
36525 BIT.B #SW1,&SW1_IN \ test switch S1 input
36526 0= IF \ case of Switch S1 pressed
36527 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
36529 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
36533 RETI \ CPU is ON, GIE is OFF
36538 \ ------------------------------\
36539 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36540 \ ******************************\
36541 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36542 \ ******************************\
36543 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36544 \ \ SMclock = 8|16|24 MHz
36545 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
36546 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
36547 \ \ SR(9)=new Toggle bit memory (ADD on)
36548 \ ------------------------------\
36549 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
36550 \ ------------------------------\
36551 \ define LPM mode for ACCEPT \
36552 \ ------------------------------\
36553 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36554 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36555 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36556 \ ------------------------------\
36557 \ RC5_FirstStartBitHalfCycle: \
36558 \ ------------------------------\
36559 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
36560 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
36561 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
36562 MOV #1778,X \ RC5_Period in us
36563 MOV #14,W \ count of loop
36565 \ ------------------------------\
36566 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
36567 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
36568 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
36569 \ RC5_Compute_3/4_Period: \ |
36570 RRUM #1,X \ X=1/2 cycle |
36574 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
36575 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
36577 \ ------------------------------\
36578 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
36579 \ ------------------------------\
36580 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36581 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
36582 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36583 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36584 SUB #1,W \ decrement count loop
36585 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
36586 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36587 0<> WHILE \ ----> out of loop ----+
36588 \ RC5_compute_7/4_Time_out: \ |
36589 ADD X,Y \ | out of bound = 7/4 period
36590 \ RC5_WaitHalfCycleP1.2_IFG: \ |
36592 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
36593 0>= IF \ | if cycle time out of bound
36594 BIC #$30,&TA0CTL \ | stop timer_A0
36595 RETI \ | then quit to do nothing
36597 \ ------------------------------\ |
36598 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
36600 MOV &TA0R,X \ | | get new RC5_period value
36601 REPEAT \ ----> loop back --+ |
36602 \ ------------------------------\ |
36603 \ RC5_SampleEndOf: \ <---------------------+
36604 \ ------------------------------\
36605 BIC #$30,&TA0CTL \ stop timer_A0
36606 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
36607 \ ******************************\
36608 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
36609 \ ******************************\
36610 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
36611 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
36612 XOR IP,X \ (new XOR old) Toggle bit (13)
36613 BIT #BIT13,X \ X(13) = New_RC5_command
36614 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
36616 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
36617 \ ******************************\
36618 \ RC5_ComputeNewRC5word \
36619 \ ******************************\
36621 MOV &BASE,2(PSP) \ save variable BASE before use
36622 MOV TOS,0(PSP) \ save TOS before use
36623 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
36624 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
36625 \ ******************************\
36626 \ RC5_ComputeC6bit \
36627 \ ******************************\
36628 BIT #$4000,IP \ test /C6 bit in IP
36629 0= IF BIS #$40,TOS \ set C6 bit in S
36630 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
36631 \ ******************************\
36632 \ RC5_CommandByteIsDone \ RC5_code --
36633 \ ******************************\
36635 \ ------------------------------\
36636 \ Display IR_RC5 code \
36637 \ ------------------------------\
36638 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
36639 \ ------------------------------\
36640 LO2HI \ switch from assembler to FORTH
36641 ['] LCD_CLEAR IS CR \ redirects CR
36642 ['] LCD_WrC IS EMIT \ redirects EMIT
36643 $10 BASE ! \ change BASE to hexadecimal
36644 CR ." $" 2 U.R \ print IR_RC5 code
36645 ['] (CR) IS CR \ restore CR
36646 ['] (EMIT) IS EMIT \ restore EMIT
36647 HI2LO \ switch from FORTH to assembler
36648 \ ------------------------------\
36649 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
36650 \ ------------------------------\
36651 MOV @PSP+,&BASE \ restore variable BASE
36652 RETI \ CPU is ON, GIE is OFF
36657 \ ------------------------------\
36658 \ TB0CTL = %0000 0010 1001 0100\$3C0
36659 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36660 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36661 \ -- \ID input divider \ 10 = /4
36662 \ -- \MC Mode Control \ 01 = up to TB0CCR0
36663 \ - \TBCLR TimerB Clear
36666 \ --------------------------------\\
36667 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36668 \ -- \CM Capture Mode
36673 \ --- \OUTMOD \ 011 = set/reset
36679 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
36681 \ ------------------------------\
36682 \ set TimerB to make 50kHz PWM \
36683 \ ------------------------------\
36684 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36685 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
36686 \ ------------------------------\
36687 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
36688 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
36689 \ ------------------------------\
36690 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36691 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
36692 \ ------------------------------\
36693 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36694 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
36695 \ ------------------------------\
36696 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
36697 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
36698 \ ------------------------------\
36699 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
36700 \ ------------------------------\
36701 \ set TimerB to generate PWM for LCD_Vo
36702 \ ------------------------------\
36703 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
36704 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
36705 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36706 \ ------------------------------\
36707 BIS.B #LCDVo,&LCDVo_DIR \
36708 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
36709 \ ------------------------------\
36710 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36711 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36712 \ ------------------------------\
36713 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36714 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36715 \ ------------------------------\
36716 \ WDT interval init part \
36717 \ ------------------------------\
36718 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
36719 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
36720 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
36721 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
36722 \ ------------------------------\
36724 \ ------------------------------\
36725 BIS.B #RC5,&IR_IE \ enable RC5_Int
36726 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36727 \ ------------------------------\
36728 \ init interrupt vectors
36729 \ ------------------------------\
36730 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
36731 MOV #RC5_INT,&IR_Vec \ init interrupt vector
36732 \ ------------------------------\
36733 \ define LPM mode for ACCEPT \
36734 \ ------------------------------\
36735 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36736 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36737 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36739 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
36741 \ ------------------------------\
36743 \ ------------------------------\
36744 $03E8 20_US \ 1- wait 20 ms
36745 $03 TOP_LCD \ 2- send DB5=DB4=1
36746 $CD 20_US \ 3- wait 4,1 ms
36747 $03 TOP_LCD \ 4- send again DB5=DB4=1
36748 $5 20_US \ 5- wait 0,1 ms
36749 $03 TOP_LCD \ 6- send again again DB5=DB4=1
36750 $2 20_US \ wait 40 us = LCD cycle
36751 $02 TOP_LCD \ 7- send DB5=1 DB4=0
36752 $2 20_US \ wait 40 us = LCD cycle
36753 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36754 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36755 LCD_Clear \ 10- "LCD_Clear"
36756 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36757 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36758 LCD_Clear \ 10- "LCD_Clear"
36759 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36760 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36762 ['] (CR) IS CR \ ' (CR) is CR
36763 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
36765 ." RC5toLCD is running. Type STOP to quit"
36766 \ NOECHO \ uncomment to run this app without terminal connexion
36767 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
36768 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
36772 : STOP \ stops multitasking, must to be used before downloading app
36773 ['] (WARM) IS WARM \ remove START app from FORTH init process
36774 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
36782 CODE MAX \ n1 n2 -- n3 signed maximum
36783 CMP @PSP,TOS \ n2-n1
36784 S< ?GOTO FW1 \ n2<n1
36790 CODE MIN \ n1 n2 -- n3 signed minimum
36791 CMP @PSP,TOS \ n2-n1
36792 S< ?GOTO BW1 \ n2<n1
36798 : U.R \ u n -- display u unsigned in n width (n >= 2)
36800 R> OVER - 0 MAX SPACES TYPE
36804 CODE 20_US \ n -- n * 20 us
36805 BEGIN \ 3 cycles loop + 6~
36806 \ MOV #5,W \ 3 MCLK = 1 MHz
36807 \ MOV #23,W \ 3 MCLK = 4 MHz
36808 MOV #51,W \ 3 MCLK = 8 MHz
36809 \ MOV #104,W \ 3 MCLK = 16 MHz
36810 \ MOV #158,W \ 3 MCLK = 24 MHz
36811 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
36821 CODE TOP_LCD \ LCD Sample
36822 \ \ if write : %xxxxWWWW --
36823 \ \ if read : -- %0000RRRR
36824 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36825 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36826 0= IF \ write LCD bits pattern
36827 AND.B #LCD_DB,TOS \
36828 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36829 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36832 THEN \ read LCD bits pattern
36835 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36836 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36837 AND.B #LCD_DB,TOS \
36842 CODE LCD_W \ byte -- write byte to LCD
36844 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
36845 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
36846 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36847 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36848 COLON \ high level word starts here
36849 TOP_LCD 2 20_US \ write high nibble first
36854 CODE LCD_WrC \ char -- Write Char
36855 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36860 CODE LCD_WrF \ func -- Write Fonction
36861 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36867 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
36872 $02 LCD_WrF 100 20_us
36876 \ : LCD_Entry_set $04 OR LCD_WrF ;
36878 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
36880 \ : LCD_Display_Shift $10 OR LCD_WrF ;
36882 \ : LCD_Fn_Set $20 OR LCD_WrF ;
36884 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
36886 \ : LCD_Goto $80 OR LCD_WrF ;
36888 \ CODE LCD_R \ -- byte read byte from LCD
36889 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36890 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36891 \ COLON \ starts a FORTH word
36892 \ TOP_LCD 2 20_us \ -- %0000HHHH
36893 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
36894 \ HI2LO \ switch from FORTH to assembler
36895 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
36896 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
36897 \ MOV @RSP+,IP \ restore IP saved by COLON
36902 \ CODE LCD_RdS \ -- status Read Status
36903 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36908 \ CODE LCD_RdC \ -- char Read Char
36909 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36914 \ -------------+------+------+------+------++---+---+---+---+---------+
36915 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
36916 \ -------------+------+------+------+------++---+---+---+---+---------+
36917 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
36918 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
36919 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
36920 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
36921 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
36922 \ -------------+------+------+------+------++---+---+---+---+---------+
36925 \ ******************************\
36926 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36927 \ ******************************\
36928 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
36929 \ ------------------------------\
36930 \ define LPM mode for ACCEPT \
36931 \ ------------------------------\
36932 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36933 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36934 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36935 BIT.B #SW2,&SW2_IN \ test switch S2
36936 0= IF \ case of switch S2 pressed
36937 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
36939 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
36942 BIT.B #SW1,&SW1_IN \ test switch S1 input
36943 0= IF \ case of Switch S1 pressed
36944 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
36946 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
36950 RETI \ CPU is ON, GIE is OFF
36955 \ ------------------------------\
36956 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36957 \ ******************************\
36958 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36959 \ ******************************\
36960 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36961 \ \ SMclock = 8|16|24 MHz
36962 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
36963 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
36964 \ \ SR(9)=new Toggle bit memory (ADD on)
36965 \ ------------------------------\
36966 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
36967 \ ------------------------------\
36968 \ define LPM mode for ACCEPT \
36969 \ ------------------------------\
36970 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36971 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36972 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36973 \ ------------------------------\
36974 \ RC5_FirstStartBitHalfCycle: \
36975 \ ------------------------------\
36976 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
36977 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
36978 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
36979 MOV #1778,X \ RC5_Period in us
36980 MOV #14,W \ count of loop
36982 \ ------------------------------\
36983 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
36984 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
36985 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
36986 \ RC5_Compute_3/4_Period: \ |
36987 RRUM #1,X \ X=1/2 cycle |
36991 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
36992 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
36994 \ ------------------------------\
36995 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
36996 \ ------------------------------\
36997 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36998 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
36999 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37000 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37001 SUB #1,W \ decrement count loop
37002 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
37003 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37004 0<> WHILE \ ----> out of loop ----+
37005 \ RC5_compute_7/4_Time_out: \ |
37006 ADD X,Y \ | out of bound = 7/4 period
37007 \ RC5_WaitHalfCycleP1.2_IFG: \ |
37009 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
37010 0>= IF \ | if cycle time out of bound
37011 BIC #$30,&TA0CTL \ | stop timer_A0
37012 RETI \ | then quit to do nothing
37014 \ ------------------------------\ |
37015 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
37017 MOV &TA0R,X \ | | get new RC5_period value
37018 REPEAT \ ----> loop back --+ |
37019 \ ------------------------------\ |
37020 \ RC5_SampleEndOf: \ <---------------------+
37021 \ ------------------------------\
37022 BIC #$30,&TA0CTL \ stop timer_A0
37023 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
37024 \ ******************************\
37025 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37026 \ ******************************\
37027 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
37028 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
37029 XOR IP,X \ (new XOR old) Toggle bit (13)
37030 BIT #BIT13,X \ X(13) = New_RC5_command
37031 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
37033 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
37034 \ ******************************\
37035 \ RC5_ComputeNewRC5word \
37036 \ ******************************\
37038 MOV &BASE,2(PSP) \ save variable BASE before use
37039 MOV TOS,0(PSP) \ save TOS before use
37040 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
37041 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
37042 \ ******************************\
37043 \ RC5_ComputeC6bit \
37044 \ ******************************\
37045 BIT #$4000,IP \ test /C6 bit in IP
37046 0= IF BIS #$40,TOS \ set C6 bit in S
37047 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
37048 \ ******************************\
37049 \ RC5_CommandByteIsDone \ RC5_code --
37050 \ ******************************\
37052 \ ------------------------------\
37053 \ Display IR_RC5 code \
37054 \ ------------------------------\
37055 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
37056 \ ------------------------------\
37057 LO2HI \ switch from assembler to FORTH
37058 ['] LCD_CLEAR IS CR \ redirects CR
37059 ['] LCD_WrC IS EMIT \ redirects EMIT
37060 $10 BASE ! \ change BASE to hexadecimal
37061 CR ." $" 2 U.R \ print IR_RC5 code
37062 ['] (CR) IS CR \ restore CR
37063 ['] (EMIT) IS EMIT \ restore EMIT
37064 HI2LO \ switch from FORTH to assembler
37065 \ ------------------------------\
37066 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
37067 \ ------------------------------\
37068 MOV @PSP+,&BASE \ restore variable BASE
37069 RETI \ CPU is ON, GIE is OFF
37074 \ ------------------------------\
37075 \ TB0CTL = %0000 0010 1001 0100\$3C0
37076 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37077 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37078 \ -- \ID input divider \ 10 = /4
37079 \ -- \MC Mode Control \ 01 = up to TB0CCR0
37080 \ - \TBCLR TimerB Clear
37083 \ --------------------------------\\
37084 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37085 \ -- \CM Capture Mode
37090 \ --- \OUTMOD \ 011 = set/reset
37096 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
37098 \ ------------------------------\
37099 \ set TimerB to make 50kHz PWM \
37100 \ ------------------------------\
37101 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37102 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
37103 \ ------------------------------\
37104 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37105 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
37106 \ ------------------------------\
37107 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37108 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
37109 \ ------------------------------\
37110 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37111 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
37112 \ ------------------------------\
37113 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37114 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
37115 \ ------------------------------\
37116 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
37117 \ ------------------------------\
37118 \ set TimerB to generate PWM for LCD_Vo
37119 \ ------------------------------\
37120 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
37121 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
37122 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37123 \ ------------------------------\
37124 BIS.B #LCDVo,&LCDVo_DIR \
37125 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
37126 \ ------------------------------\
37127 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37128 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37129 \ ------------------------------\
37130 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37131 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37132 \ ------------------------------\
37133 \ WDT interval init part \
37134 \ ------------------------------\
37135 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
37136 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
37137 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
37138 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
37139 \ ------------------------------\
37141 \ ------------------------------\
37142 BIS.B #RC5,&IR_IE \ enable RC5_Int
37143 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37144 \ ------------------------------\
37145 \ init interrupt vectors
37146 \ ------------------------------\
37147 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
37148 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37149 \ ------------------------------\
37150 \ define LPM mode for ACCEPT \
37151 \ ------------------------------\
37152 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37153 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37154 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37156 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
37158 \ ------------------------------\
37160 \ ------------------------------\
37161 $03E8 20_US \ 1- wait 20 ms
37162 $03 TOP_LCD \ 2- send DB5=DB4=1
37163 $CD 20_US \ 3- wait 4,1 ms
37164 $03 TOP_LCD \ 4- send again DB5=DB4=1
37165 $5 20_US \ 5- wait 0,1 ms
37166 $03 TOP_LCD \ 6- send again again DB5=DB4=1
37167 $2 20_US \ wait 40 us = LCD cycle
37168 $02 TOP_LCD \ 7- send DB5=1 DB4=0
37169 $2 20_US \ wait 40 us = LCD cycle
37170 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37171 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37172 LCD_Clear \ 10- "LCD_Clear"
37173 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37174 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37175 LCD_Clear \ 10- "LCD_Clear"
37176 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37177 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37179 ['] (CR) IS CR \ ' (CR) is CR
37180 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
37182 ." RC5toLCD is running. Type STOP to quit"
37183 \ NOECHO \ uncomment to run this app without terminal connexion
37184 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
37185 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
37189 : STOP \ stops multitasking, must to be used before downloading app
37190 ['] (WARM) IS WARM \ remove START app from FORTH init process
37191 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
37199 CODE MAX \ n1 n2 -- n3 signed maximum
37200 CMP @PSP,TOS \ n2-n1
37201 S< ?GOTO FW1 \ n2<n1
37207 CODE MIN \ n1 n2 -- n3 signed minimum
37208 CMP @PSP,TOS \ n2-n1
37209 S< ?GOTO BW1 \ n2<n1
37215 : U.R \ u n -- display u unsigned in n width (n >= 2)
37217 R> OVER - 0 MAX SPACES TYPE
37221 CODE 20_US \ n -- n * 20 us
37222 BEGIN \ 3 cycles loop + 6~
37223 \ MOV #5,W \ 3 MCLK = 1 MHz
37224 \ MOV #23,W \ 3 MCLK = 4 MHz
37225 MOV #51,W \ 3 MCLK = 8 MHz
37226 \ MOV #104,W \ 3 MCLK = 16 MHz
37227 \ MOV #158,W \ 3 MCLK = 24 MHz
37228 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
37238 CODE TOP_LCD \ LCD Sample
37239 \ \ if write : %xxxxWWWW --
37240 \ \ if read : -- %0000RRRR
37241 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37242 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37243 0= IF \ write LCD bits pattern
37244 AND.B #LCD_DB,TOS \
37245 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37246 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37249 THEN \ read LCD bits pattern
37252 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37253 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37254 AND.B #LCD_DB,TOS \
37259 CODE LCD_W \ byte -- write byte to LCD
37261 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
37262 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
37263 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37264 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37265 COLON \ high level word starts here
37266 TOP_LCD 2 20_US \ write high nibble first
37271 CODE LCD_WrC \ char -- Write Char
37272 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37277 CODE LCD_WrF \ func -- Write Fonction
37278 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37284 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
37289 $02 LCD_WrF 100 20_us
37293 \ : LCD_Entry_set $04 OR LCD_WrF ;
37295 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
37297 \ : LCD_Display_Shift $10 OR LCD_WrF ;
37299 \ : LCD_Fn_Set $20 OR LCD_WrF ;
37301 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
37303 \ : LCD_Goto $80 OR LCD_WrF ;
37305 \ CODE LCD_R \ -- byte read byte from LCD
37306 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37307 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37308 \ COLON \ starts a FORTH word
37309 \ TOP_LCD 2 20_us \ -- %0000HHHH
37310 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
37311 \ HI2LO \ switch from FORTH to assembler
37312 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
37313 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
37314 \ MOV @RSP+,IP \ restore IP saved by COLON
37319 \ CODE LCD_RdS \ -- status Read Status
37320 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37325 \ CODE LCD_RdC \ -- char Read Char
37326 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37331 \ -------------+------+------+------+------++---+---+---+---+---------+
37332 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
37333 \ -------------+------+------+------+------++---+---+---+---+---------+
37334 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
37335 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
37336 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
37337 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
37338 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
37339 \ -------------+------+------+------+------++---+---+---+---+---------+
37342 \ ******************************\
37343 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
37344 \ ******************************\
37345 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
37346 \ ------------------------------\
37347 \ define LPM mode for ACCEPT \
37348 \ ------------------------------\
37349 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37350 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37351 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37352 BIT.B #SW2,&SW2_IN \ test switch S2
37353 0= IF \ case of switch S2 pressed
37354 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
37356 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
37359 BIT.B #SW1,&SW1_IN \ test switch S1 input
37360 0= IF \ case of Switch S1 pressed
37361 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
37363 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
37367 RETI \ CPU is ON, GIE is OFF
37372 \ ------------------------------\
37373 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
37374 \ ******************************\
37375 ASM RC5_INT \ wake up on Px.RC5 change interrupt
37376 \ ******************************\
37377 \ \ in : SR(9)=old Toggle bit memory (ADD on)
37378 \ \ SMclock = 8|16|24 MHz
37379 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
37380 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
37381 \ \ SR(9)=new Toggle bit memory (ADD on)
37382 \ ------------------------------\
37383 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
37384 \ ------------------------------\
37385 \ define LPM mode for ACCEPT \
37386 \ ------------------------------\
37387 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37388 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37389 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37390 \ ------------------------------\
37391 \ RC5_FirstStartBitHalfCycle: \
37392 \ ------------------------------\
37393 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
37394 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
37395 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
37396 MOV #1778,X \ RC5_Period in us
37397 MOV #14,W \ count of loop
37399 \ ------------------------------\
37400 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
37401 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
37402 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
37403 \ RC5_Compute_3/4_Period: \ |
37404 RRUM #1,X \ X=1/2 cycle |
37408 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
37409 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
37411 \ ------------------------------\
37412 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
37413 \ ------------------------------\
37414 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37415 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
37416 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37417 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37418 SUB #1,W \ decrement count loop
37419 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
37420 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37421 0<> WHILE \ ----> out of loop ----+
37422 \ RC5_compute_7/4_Time_out: \ |
37423 ADD X,Y \ | out of bound = 7/4 period
37424 \ RC5_WaitHalfCycleP1.2_IFG: \ |
37426 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
37427 0>= IF \ | if cycle time out of bound
37428 BIC #$30,&TA0CTL \ | stop timer_A0
37429 RETI \ | then quit to do nothing
37431 \ ------------------------------\ |
37432 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
37434 MOV &TA0R,X \ | | get new RC5_period value
37435 REPEAT \ ----> loop back --+ |
37436 \ ------------------------------\ |
37437 \ RC5_SampleEndOf: \ <---------------------+
37438 \ ------------------------------\
37439 BIC #$30,&TA0CTL \ stop timer_A0
37440 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
37441 \ ******************************\
37442 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37443 \ ******************************\
37444 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
37445 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
37446 XOR IP,X \ (new XOR old) Toggle bit (13)
37447 BIT #BIT13,X \ X(13) = New_RC5_command
37448 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
37450 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
37451 \ ******************************\
37452 \ RC5_ComputeNewRC5word \
37453 \ ******************************\
37455 MOV &BASE,2(PSP) \ save variable BASE before use
37456 MOV TOS,0(PSP) \ save TOS before use
37457 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
37458 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
37459 \ ******************************\
37460 \ RC5_ComputeC6bit \
37461 \ ******************************\
37462 BIT #$4000,IP \ test /C6 bit in IP
37463 0= IF BIS #$40,TOS \ set C6 bit in S
37464 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
37465 \ ******************************\
37466 \ RC5_CommandByteIsDone \ RC5_code --
37467 \ ******************************\
37469 \ ------------------------------\
37470 \ Display IR_RC5 code \
37471 \ ------------------------------\
37472 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
37473 \ ------------------------------\
37474 LO2HI \ switch from assembler to FORTH
37475 ['] LCD_CLEAR IS CR \ redirects CR
37476 ['] LCD_WrC IS EMIT \ redirects EMIT
37477 $10 BASE ! \ change BASE to hexadecimal
37478 CR ." $" 2 U.R \ print IR_RC5 code
37479 ['] (CR) IS CR \ restore CR
37480 ['] (EMIT) IS EMIT \ restore EMIT
37481 HI2LO \ switch from FORTH to assembler
37482 \ ------------------------------\
37483 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
37484 \ ------------------------------\
37485 MOV @PSP+,&BASE \ restore variable BASE
37486 RETI \ CPU is ON, GIE is OFF
37491 \ ------------------------------\
37492 \ TB0CTL = %0000 0010 1001 0100\$3C0
37493 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37494 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37495 \ -- \ID input divider \ 10 = /4
37496 \ -- \MC Mode Control \ 01 = up to TB0CCR0
37497 \ - \TBCLR TimerB Clear
37500 \ --------------------------------\\
37501 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37502 \ -- \CM Capture Mode
37507 \ --- \OUTMOD \ 011 = set/reset
37513 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
37515 \ ------------------------------\
37516 \ set TimerB to make 50kHz PWM \
37517 \ ------------------------------\
37518 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37519 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
37520 \ ------------------------------\
37521 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37522 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
37523 \ ------------------------------\
37524 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37525 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
37526 \ ------------------------------\
37527 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37528 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
37529 \ ------------------------------\
37530 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37531 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
37532 \ ------------------------------\
37533 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
37534 \ ------------------------------\
37535 \ set TimerB to generate PWM for LCD_Vo
37536 \ ------------------------------\
37537 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
37538 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
37539 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37540 \ ------------------------------\
37541 BIS.B #LCDVo,&LCDVo_DIR \
37542 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
37543 \ ------------------------------\
37544 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37545 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37546 \ ------------------------------\
37547 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37548 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37549 \ ------------------------------\
37550 \ WDT interval init part \
37551 \ ------------------------------\
37552 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
37553 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
37554 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
37555 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
37556 \ ------------------------------\
37558 \ ------------------------------\
37559 BIS.B #RC5,&IR_IE \ enable RC5_Int
37560 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37561 \ ------------------------------\
37562 \ init interrupt vectors
37563 \ ------------------------------\
37564 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
37565 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37566 \ ------------------------------\
37567 \ define LPM mode for ACCEPT \
37568 \ ------------------------------\
37569 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37570 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37571 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37573 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
37575 \ ------------------------------\
37577 \ ------------------------------\
37578 $03E8 20_US \ 1- wait 20 ms
37579 $03 TOP_LCD \ 2- send DB5=DB4=1
37580 $CD 20_US \ 3- wait 4,1 ms
37581 $03 TOP_LCD \ 4- send again DB5=DB4=1
37582 $5 20_US \ 5- wait 0,1 ms
37583 $03 TOP_LCD \ 6- send again again DB5=DB4=1
37584 $2 20_US \ wait 40 us = LCD cycle
37585 $02 TOP_LCD \ 7- send DB5=1 DB4=0
37586 $2 20_US \ wait 40 us = LCD cycle
37587 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37588 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37589 LCD_Clear \ 10- "LCD_Clear"
37590 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37591 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37592 LCD_Clear \ 10- "LCD_Clear"
37593 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37594 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37596 ['] (CR) IS CR \ ' (CR) is CR
37597 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
37599 ." RC5toLCD is running. Type STOP to quit"
37600 \ NOECHO \ uncomment to run this app without terminal connexion
37601 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
37602 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
37606 : STOP \ stops multitasking, must to be used before downloading app
37607 ['] (WARM) IS WARM \ remove START app from FORTH init process
37608 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
37616 CODE MAX \ n1 n2 -- n3 signed maximum
37617 CMP @PSP,TOS \ n2-n1
37618 S< ?GOTO FW1 \ n2<n1
37624 CODE MIN \ n1 n2 -- n3 signed minimum
37625 CMP @PSP,TOS \ n2-n1
37626 S< ?GOTO BW1 \ n2<n1
37632 : U.R \ u n -- display u unsigned in n width (n >= 2)
37634 R> OVER - 0 MAX SPACES TYPE
37638 CODE 20_US \ n -- n * 20 us
37639 BEGIN \ 3 cycles loop + 6~
37640 \ MOV #5,W \ 3 MCLK = 1 MHz
37641 \ MOV #23,W \ 3 MCLK = 4 MHz
37642 MOV #51,W \ 3 MCLK = 8 MHz
37643 \ MOV #104,W \ 3 MCLK = 16 MHz
37644 \ MOV #158,W \ 3 MCLK = 24 MHz
37645 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
37655 CODE TOP_LCD \ LCD Sample
37656 \ \ if write : %xxxxWWWW --
37657 \ \ if read : -- %0000RRRR
37658 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37659 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37660 0= IF \ write LCD bits pattern
37661 AND.B #LCD_DB,TOS \
37662 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37663 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37666 THEN \ read LCD bits pattern
37669 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37670 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37671 AND.B #LCD_DB,TOS \
37676 CODE LCD_W \ byte -- write byte to LCD
37678 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
37679 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
37680 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37681 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37682 COLON \ high level word starts here
37683 TOP_LCD 2 20_US \ write high nibble first
37688 CODE LCD_WrC \ char -- Write Char
37689 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37694 CODE LCD_WrF \ func -- Write Fonction
37695 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37701 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
37706 $02 LCD_WrF 100 20_us
37710 \ : LCD_Entry_set $04 OR LCD_WrF ;
37712 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
37714 \ : LCD_Display_Shift $10 OR LCD_WrF ;
37716 \ : LCD_Fn_Set $20 OR LCD_WrF ;
37718 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
37720 \ : LCD_Goto $80 OR LCD_WrF ;
37722 \ CODE LCD_R \ -- byte read byte from LCD
37723 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37724 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37725 \ COLON \ starts a FORTH word
37726 \ TOP_LCD 2 20_us \ -- %0000HHHH
37727 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
37728 \ HI2LO \ switch from FORTH to assembler
37729 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
37730 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
37731 \ MOV @RSP+,IP \ restore IP saved by COLON
37736 \ CODE LCD_RdS \ -- status Read Status
37737 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37742 \ CODE LCD_RdC \ -- char Read Char
37743 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37748 \ -------------+------+------+------+------++---+---+---+---+---------+
37749 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
37750 \ -------------+------+------+------+------++---+---+---+---+---------+
37751 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
37752 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
37753 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
37754 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
37755 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
37756 \ -------------+------+------+------+------++---+---+---+---+---------+
37759 \ ******************************\
37760 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
37761 \ ******************************\
37762 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
37763 \ ------------------------------\
37764 \ define LPM mode for ACCEPT \
37765 \ ------------------------------\
37766 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37767 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37768 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37769 BIT.B #SW2,&SW2_IN \ test switch S2
37770 0= IF \ case of switch S2 pressed
37771 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
37773 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
37776 BIT.B #SW1,&SW1_IN \ test switch S1 input
37777 0= IF \ case of Switch S1 pressed
37778 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
37780 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
37784 RETI \ CPU is ON, GIE is OFF
37789 \ ------------------------------\
37790 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
37791 \ ******************************\
37792 ASM RC5_INT \ wake up on Px.RC5 change interrupt
37793 \ ******************************\
37794 \ \ in : SR(9)=old Toggle bit memory (ADD on)
37795 \ \ SMclock = 8|16|24 MHz
37796 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
37797 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
37798 \ \ SR(9)=new Toggle bit memory (ADD on)
37799 \ ------------------------------\
37800 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
37801 \ ------------------------------\
37802 \ define LPM mode for ACCEPT \
37803 \ ------------------------------\
37804 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37805 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37806 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37807 \ ------------------------------\
37808 \ RC5_FirstStartBitHalfCycle: \
37809 \ ------------------------------\
37810 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
37811 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
37812 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
37813 MOV #1778,X \ RC5_Period in us
37814 MOV #14,W \ count of loop
37816 \ ------------------------------\
37817 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
37818 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
37819 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
37820 \ RC5_Compute_3/4_Period: \ |
37821 RRUM #1,X \ X=1/2 cycle |
37825 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
37826 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
37828 \ ------------------------------\
37829 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
37830 \ ------------------------------\
37831 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37832 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
37833 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37834 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37835 SUB #1,W \ decrement count loop
37836 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
37837 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37838 0<> WHILE \ ----> out of loop ----+
37839 \ RC5_compute_7/4_Time_out: \ |
37840 ADD X,Y \ | out of bound = 7/4 period
37841 \ RC5_WaitHalfCycleP1.2_IFG: \ |
37843 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
37844 0>= IF \ | if cycle time out of bound
37845 BIC #$30,&TA0CTL \ | stop timer_A0
37846 RETI \ | then quit to do nothing
37848 \ ------------------------------\ |
37849 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
37851 MOV &TA0R,X \ | | get new RC5_period value
37852 REPEAT \ ----> loop back --+ |
37853 \ ------------------------------\ |
37854 \ RC5_SampleEndOf: \ <---------------------+
37855 \ ------------------------------\
37856 BIC #$30,&TA0CTL \ stop timer_A0
37857 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
37858 \ ******************************\
37859 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37860 \ ******************************\
37861 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
37862 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
37863 XOR IP,X \ (new XOR old) Toggle bit (13)
37864 BIT #BIT13,X \ X(13) = New_RC5_command
37865 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
37867 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
37868 \ ******************************\
37869 \ RC5_ComputeNewRC5word \
37870 \ ******************************\
37872 MOV &BASE,2(PSP) \ save variable BASE before use
37873 MOV TOS,0(PSP) \ save TOS before use
37874 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
37875 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
37876 \ ******************************\
37877 \ RC5_ComputeC6bit \
37878 \ ******************************\
37879 BIT #$4000,IP \ test /C6 bit in IP
37880 0= IF BIS #$40,TOS \ set C6 bit in S
37881 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
37882 \ ******************************\
37883 \ RC5_CommandByteIsDone \ RC5_code --
37884 \ ******************************\
37886 \ ------------------------------\
37887 \ Display IR_RC5 code \
37888 \ ------------------------------\
37889 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
37890 \ ------------------------------\
37891 LO2HI \ switch from assembler to FORTH
37892 ['] LCD_CLEAR IS CR \ redirects CR
37893 ['] LCD_WrC IS EMIT \ redirects EMIT
37894 $10 BASE ! \ change BASE to hexadecimal
37895 CR ." $" 2 U.R \ print IR_RC5 code
37896 ['] (CR) IS CR \ restore CR
37897 ['] (EMIT) IS EMIT \ restore EMIT
37898 HI2LO \ switch from FORTH to assembler
37899 \ ------------------------------\
37900 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
37901 \ ------------------------------\
37902 MOV @PSP+,&BASE \ restore variable BASE
37903 RETI \ CPU is ON, GIE is OFF
37908 \ ------------------------------\
37909 \ TB0CTL = %0000 0010 1001 0100\$3C0
37910 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37911 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37912 \ -- \ID input divider \ 10 = /4
37913 \ -- \MC Mode Control \ 01 = up to TB0CCR0
37914 \ - \TBCLR TimerB Clear
37917 \ --------------------------------\\
37918 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37919 \ -- \CM Capture Mode
37924 \ --- \OUTMOD \ 011 = set/reset
37930 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
37932 \ ------------------------------\
37933 \ set TimerB to make 50kHz PWM \
37934 \ ------------------------------\
37935 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37936 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
37937 \ ------------------------------\
37938 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
37939 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
37940 \ ------------------------------\
37941 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37942 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
37943 \ ------------------------------\
37944 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37945 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
37946 \ ------------------------------\
37947 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
37948 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
37949 \ ------------------------------\
37950 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
37951 \ ------------------------------\
37952 \ set TimerB to generate PWM for LCD_Vo
37953 \ ------------------------------\
37954 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
37955 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
37956 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37957 \ ------------------------------\
37958 BIS.B #LCDVo,&LCDVo_DIR \
37959 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
37960 \ ------------------------------\
37961 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37962 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37963 \ ------------------------------\
37964 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37965 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37966 \ ------------------------------\
37967 \ WDT interval init part \
37968 \ ------------------------------\
37969 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
37970 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
37971 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
37972 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
37973 \ ------------------------------\
37975 \ ------------------------------\
37976 BIS.B #RC5,&IR_IE \ enable RC5_Int
37977 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37978 \ ------------------------------\
37979 \ init interrupt vectors
37980 \ ------------------------------\
37981 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
37982 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37983 \ ------------------------------\
37984 \ define LPM mode for ACCEPT \
37985 \ ------------------------------\
37986 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37987 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37988 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37990 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
37992 \ ------------------------------\
37994 \ ------------------------------\
37995 $03E8 20_US \ 1- wait 20 ms
37996 $03 TOP_LCD \ 2- send DB5=DB4=1
37997 $CD 20_US \ 3- wait 4,1 ms
37998 $03 TOP_LCD \ 4- send again DB5=DB4=1
37999 $5 20_US \ 5- wait 0,1 ms
38000 $03 TOP_LCD \ 6- send again again DB5=DB4=1
38001 $2 20_US \ wait 40 us = LCD cycle
38002 $02 TOP_LCD \ 7- send DB5=1 DB4=0
38003 $2 20_US \ wait 40 us = LCD cycle
38004 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38005 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38006 LCD_Clear \ 10- "LCD_Clear"
38007 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38008 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38009 LCD_Clear \ 10- "LCD_Clear"
38010 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38011 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38013 ['] (CR) IS CR \ ' (CR) is CR
38014 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
38016 ." RC5toLCD is running. Type STOP to quit"
38017 \ NOECHO \ uncomment to run this app without terminal connexion
38018 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
38019 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
38023 : STOP \ stops multitasking, must to be used before downloading app
38024 ['] (WARM) IS WARM \ remove START app from FORTH init process
38025 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
38033 CODE MAX \ n1 n2 -- n3 signed maximum
38034 CMP @PSP,TOS \ n2-n1
38035 S< ?GOTO FW1 \ n2<n1
38041 CODE MIN \ n1 n2 -- n3 signed minimum
38042 CMP @PSP,TOS \ n2-n1
38043 S< ?GOTO BW1 \ n2<n1
38049 : U.R \ u n -- display u unsigned in n width (n >= 2)
38051 R> OVER - 0 MAX SPACES TYPE
38055 CODE 20_US \ n -- n * 20 us
38056 BEGIN \ 3 cycles loop + 6~
38057 \ MOV #5,W \ 3 MCLK = 1 MHz
38058 \ MOV #23,W \ 3 MCLK = 4 MHz
38059 MOV #51,W \ 3 MCLK = 8 MHz
38060 \ MOV #104,W \ 3 MCLK = 16 MHz
38061 \ MOV #158,W \ 3 MCLK = 24 MHz
38062 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
38072 CODE TOP_LCD \ LCD Sample
38073 \ \ if write : %xxxxWWWW --
38074 \ \ if read : -- %0000RRRR
38075 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38076 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38077 0= IF \ write LCD bits pattern
38078 AND.B #LCD_DB,TOS \
38079 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38080 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38083 THEN \ read LCD bits pattern
38086 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38087 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38088 AND.B #LCD_DB,TOS \
38093 CODE LCD_W \ byte -- write byte to LCD
38095 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
38096 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
38097 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38098 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38099 COLON \ high level word starts here
38100 TOP_LCD 2 20_US \ write high nibble first
38105 CODE LCD_WrC \ char -- Write Char
38106 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38111 CODE LCD_WrF \ func -- Write Fonction
38112 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38118 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
38123 $02 LCD_WrF 100 20_us
38127 \ : LCD_Entry_set $04 OR LCD_WrF ;
38129 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
38131 \ : LCD_Display_Shift $10 OR LCD_WrF ;
38133 \ : LCD_Fn_Set $20 OR LCD_WrF ;
38135 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
38137 \ : LCD_Goto $80 OR LCD_WrF ;
38139 \ CODE LCD_R \ -- byte read byte from LCD
38140 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38141 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38142 \ COLON \ starts a FORTH word
38143 \ TOP_LCD 2 20_us \ -- %0000HHHH
38144 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
38145 \ HI2LO \ switch from FORTH to assembler
38146 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
38147 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
38148 \ MOV @RSP+,IP \ restore IP saved by COLON
38153 \ CODE LCD_RdS \ -- status Read Status
38154 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38159 \ CODE LCD_RdC \ -- char Read Char
38160 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38165 \ -------------+------+------+------+------++---+---+---+---+---------+
38166 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
38167 \ -------------+------+------+------+------++---+---+---+---+---------+
38168 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
38169 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
38170 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
38171 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
38172 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
38173 \ -------------+------+------+------+------++---+---+---+---+---------+
38176 \ ******************************\
38177 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38178 \ ******************************\
38179 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
38180 \ ------------------------------\
38181 \ define LPM mode for ACCEPT \
38182 \ ------------------------------\
38183 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38184 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38185 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38186 BIT.B #SW2,&SW2_IN \ test switch S2
38187 0= IF \ case of switch S2 pressed
38188 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
38190 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
38193 BIT.B #SW1,&SW1_IN \ test switch S1 input
38194 0= IF \ case of Switch S1 pressed
38195 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
38197 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
38201 RETI \ CPU is ON, GIE is OFF
38206 \ ------------------------------\
38207 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38208 \ ******************************\
38209 ASM RC5_INT \ wake up on Px.RC5 change interrupt
38210 \ ******************************\
38211 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38212 \ \ SMclock = 8|16|24 MHz
38213 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
38214 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
38215 \ \ SR(9)=new Toggle bit memory (ADD on)
38216 \ ------------------------------\
38217 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
38218 \ ------------------------------\
38219 \ define LPM mode for ACCEPT \
38220 \ ------------------------------\
38221 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38222 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38223 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38224 \ ------------------------------\
38225 \ RC5_FirstStartBitHalfCycle: \
38226 \ ------------------------------\
38227 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
38228 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
38229 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
38230 MOV #1778,X \ RC5_Period in us
38231 MOV #14,W \ count of loop
38233 \ ------------------------------\
38234 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
38235 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
38236 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
38237 \ RC5_Compute_3/4_Period: \ |
38238 RRUM #1,X \ X=1/2 cycle |
38242 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
38243 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
38245 \ ------------------------------\
38246 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
38247 \ ------------------------------\
38248 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38249 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
38250 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38251 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38252 SUB #1,W \ decrement count loop
38253 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
38254 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38255 0<> WHILE \ ----> out of loop ----+
38256 \ RC5_compute_7/4_Time_out: \ |
38257 ADD X,Y \ | out of bound = 7/4 period
38258 \ RC5_WaitHalfCycleP1.2_IFG: \ |
38260 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
38261 0>= IF \ | if cycle time out of bound
38262 BIC #$30,&TA0CTL \ | stop timer_A0
38263 RETI \ | then quit to do nothing
38265 \ ------------------------------\ |
38266 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
38268 MOV &TA0R,X \ | | get new RC5_period value
38269 REPEAT \ ----> loop back --+ |
38270 \ ------------------------------\ |
38271 \ RC5_SampleEndOf: \ <---------------------+
38272 \ ------------------------------\
38273 BIC #$30,&TA0CTL \ stop timer_A0
38274 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
38275 \ ******************************\
38276 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
38277 \ ******************************\
38278 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
38279 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
38280 XOR IP,X \ (new XOR old) Toggle bit (13)
38281 BIT #BIT13,X \ X(13) = New_RC5_command
38282 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
38284 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
38285 \ ******************************\
38286 \ RC5_ComputeNewRC5word \
38287 \ ******************************\
38289 MOV &BASE,2(PSP) \ save variable BASE before use
38290 MOV TOS,0(PSP) \ save TOS before use
38291 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
38292 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
38293 \ ******************************\
38294 \ RC5_ComputeC6bit \
38295 \ ******************************\
38296 BIT #$4000,IP \ test /C6 bit in IP
38297 0= IF BIS #$40,TOS \ set C6 bit in S
38298 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
38299 \ ******************************\
38300 \ RC5_CommandByteIsDone \ RC5_code --
38301 \ ******************************\
38303 \ ------------------------------\
38304 \ Display IR_RC5 code \
38305 \ ------------------------------\
38306 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
38307 \ ------------------------------\
38308 LO2HI \ switch from assembler to FORTH
38309 ['] LCD_CLEAR IS CR \ redirects CR
38310 ['] LCD_WrC IS EMIT \ redirects EMIT
38311 $10 BASE ! \ change BASE to hexadecimal
38312 CR ." $" 2 U.R \ print IR_RC5 code
38313 ['] (CR) IS CR \ restore CR
38314 ['] (EMIT) IS EMIT \ restore EMIT
38315 HI2LO \ switch from FORTH to assembler
38316 \ ------------------------------\
38317 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
38318 \ ------------------------------\
38319 MOV @PSP+,&BASE \ restore variable BASE
38320 RETI \ CPU is ON, GIE is OFF
38325 \ ------------------------------\
38326 \ TB0CTL = %0000 0010 1001 0100\$3C0
38327 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38328 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38329 \ -- \ID input divider \ 10 = /4
38330 \ -- \MC Mode Control \ 01 = up to TB0CCR0
38331 \ - \TBCLR TimerB Clear
38334 \ --------------------------------\\
38335 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38336 \ -- \CM Capture Mode
38341 \ --- \OUTMOD \ 011 = set/reset
38347 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
38349 \ ------------------------------\
38350 \ set TimerB to make 50kHz PWM \
38351 \ ------------------------------\
38352 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38353 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
38354 \ ------------------------------\
38355 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38356 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
38357 \ ------------------------------\
38358 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38359 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
38360 \ ------------------------------\
38361 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38362 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
38363 \ ------------------------------\
38364 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38365 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
38366 \ ------------------------------\
38367 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
38368 \ ------------------------------\
38369 \ set TimerB to generate PWM for LCD_Vo
38370 \ ------------------------------\
38371 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
38372 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
38373 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38374 \ ------------------------------\
38375 BIS.B #LCDVo,&LCDVo_DIR \
38376 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
38377 \ ------------------------------\
38378 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38379 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38380 \ ------------------------------\
38381 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38382 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38383 \ ------------------------------\
38384 \ WDT interval init part \
38385 \ ------------------------------\
38386 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
38387 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
38388 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
38389 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
38390 \ ------------------------------\
38392 \ ------------------------------\
38393 BIS.B #RC5,&IR_IE \ enable RC5_Int
38394 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38395 \ ------------------------------\
38396 \ init interrupt vectors
38397 \ ------------------------------\
38398 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
38399 MOV #RC5_INT,&IR_Vec \ init interrupt vector
38400 \ ------------------------------\
38401 \ define LPM mode for ACCEPT \
38402 \ ------------------------------\
38403 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38404 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38405 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38407 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
38409 \ ------------------------------\
38411 \ ------------------------------\
38412 $03E8 20_US \ 1- wait 20 ms
38413 $03 TOP_LCD \ 2- send DB5=DB4=1
38414 $CD 20_US \ 3- wait 4,1 ms
38415 $03 TOP_LCD \ 4- send again DB5=DB4=1
38416 $5 20_US \ 5- wait 0,1 ms
38417 $03 TOP_LCD \ 6- send again again DB5=DB4=1
38418 $2 20_US \ wait 40 us = LCD cycle
38419 $02 TOP_LCD \ 7- send DB5=1 DB4=0
38420 $2 20_US \ wait 40 us = LCD cycle
38421 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38422 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38423 LCD_Clear \ 10- "LCD_Clear"
38424 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38425 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38426 LCD_Clear \ 10- "LCD_Clear"
38427 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38428 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38430 ['] (CR) IS CR \ ' (CR) is CR
38431 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
38433 ." RC5toLCD is running. Type STOP to quit"
38434 \ NOECHO \ uncomment to run this app without terminal connexion
38435 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
38436 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
38440 : STOP \ stops multitasking, must to be used before downloading app
38441 ['] (WARM) IS WARM \ remove START app from FORTH init process
38442 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
38450 CODE MAX \ n1 n2 -- n3 signed maximum
38451 CMP @PSP,TOS \ n2-n1
38452 S< ?GOTO FW1 \ n2<n1
38458 CODE MIN \ n1 n2 -- n3 signed minimum
38459 CMP @PSP,TOS \ n2-n1
38460 S< ?GOTO BW1 \ n2<n1
38466 : U.R \ u n -- display u unsigned in n width (n >= 2)
38468 R> OVER - 0 MAX SPACES TYPE
38472 CODE 20_US \ n -- n * 20 us
38473 BEGIN \ 3 cycles loop + 6~
38474 \ MOV #5,W \ 3 MCLK = 1 MHz
38475 \ MOV #23,W \ 3 MCLK = 4 MHz
38476 MOV #51,W \ 3 MCLK = 8 MHz
38477 \ MOV #104,W \ 3 MCLK = 16 MHz
38478 \ MOV #158,W \ 3 MCLK = 24 MHz
38479 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
38489 CODE TOP_LCD \ LCD Sample
38490 \ \ if write : %xxxxWWWW --
38491 \ \ if read : -- %0000RRRR
38492 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38493 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38494 0= IF \ write LCD bits pattern
38495 AND.B #LCD_DB,TOS \
38496 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38497 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38500 THEN \ read LCD bits pattern
38503 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38504 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38505 AND.B #LCD_DB,TOS \
38510 CODE LCD_W \ byte -- write byte to LCD
38512 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
38513 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
38514 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38515 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38516 COLON \ high level word starts here
38517 TOP_LCD 2 20_US \ write high nibble first
38522 CODE LCD_WrC \ char -- Write Char
38523 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38528 CODE LCD_WrF \ func -- Write Fonction
38529 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38535 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
38540 $02 LCD_WrF 100 20_us
38544 \ : LCD_Entry_set $04 OR LCD_WrF ;
38546 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
38548 \ : LCD_Display_Shift $10 OR LCD_WrF ;
38550 \ : LCD_Fn_Set $20 OR LCD_WrF ;
38552 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
38554 \ : LCD_Goto $80 OR LCD_WrF ;
38556 \ CODE LCD_R \ -- byte read byte from LCD
38557 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38558 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38559 \ COLON \ starts a FORTH word
38560 \ TOP_LCD 2 20_us \ -- %0000HHHH
38561 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
38562 \ HI2LO \ switch from FORTH to assembler
38563 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
38564 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
38565 \ MOV @RSP+,IP \ restore IP saved by COLON
38570 \ CODE LCD_RdS \ -- status Read Status
38571 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38576 \ CODE LCD_RdC \ -- char Read Char
38577 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38582 \ -------------+------+------+------+------++---+---+---+---+---------+
38583 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
38584 \ -------------+------+------+------+------++---+---+---+---+---------+
38585 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
38586 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
38587 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
38588 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
38589 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
38590 \ -------------+------+------+------+------++---+---+---+---+---------+
38593 \ ******************************\
38594 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38595 \ ******************************\
38596 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
38597 \ ------------------------------\
38598 \ define LPM mode for ACCEPT \
38599 \ ------------------------------\
38600 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38601 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38602 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38603 BIT.B #SW2,&SW2_IN \ test switch S2
38604 0= IF \ case of switch S2 pressed
38605 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
38607 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
38610 BIT.B #SW1,&SW1_IN \ test switch S1 input
38611 0= IF \ case of Switch S1 pressed
38612 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
38614 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
38618 RETI \ CPU is ON, GIE is OFF
38623 \ ------------------------------\
38624 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38625 \ ******************************\
38626 ASM RC5_INT \ wake up on Px.RC5 change interrupt
38627 \ ******************************\
38628 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38629 \ \ SMclock = 8|16|24 MHz
38630 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
38631 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
38632 \ \ SR(9)=new Toggle bit memory (ADD on)
38633 \ ------------------------------\
38634 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
38635 \ ------------------------------\
38636 \ define LPM mode for ACCEPT \
38637 \ ------------------------------\
38638 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38639 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38640 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38641 \ ------------------------------\
38642 \ RC5_FirstStartBitHalfCycle: \
38643 \ ------------------------------\
38644 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
38645 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
38646 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
38647 MOV #1778,X \ RC5_Period in us
38648 MOV #14,W \ count of loop
38650 \ ------------------------------\
38651 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
38652 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
38653 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
38654 \ RC5_Compute_3/4_Period: \ |
38655 RRUM #1,X \ X=1/2 cycle |
38659 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
38660 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
38662 \ ------------------------------\
38663 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
38664 \ ------------------------------\
38665 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38666 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
38667 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38668 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38669 SUB #1,W \ decrement count loop
38670 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
38671 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38672 0<> WHILE \ ----> out of loop ----+
38673 \ RC5_compute_7/4_Time_out: \ |
38674 ADD X,Y \ | out of bound = 7/4 period
38675 \ RC5_WaitHalfCycleP1.2_IFG: \ |
38677 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
38678 0>= IF \ | if cycle time out of bound
38679 BIC #$30,&TA0CTL \ | stop timer_A0
38680 RETI \ | then quit to do nothing
38682 \ ------------------------------\ |
38683 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
38685 MOV &TA0R,X \ | | get new RC5_period value
38686 REPEAT \ ----> loop back --+ |
38687 \ ------------------------------\ |
38688 \ RC5_SampleEndOf: \ <---------------------+
38689 \ ------------------------------\
38690 BIC #$30,&TA0CTL \ stop timer_A0
38691 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
38692 \ ******************************\
38693 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
38694 \ ******************************\
38695 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
38696 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
38697 XOR IP,X \ (new XOR old) Toggle bit (13)
38698 BIT #BIT13,X \ X(13) = New_RC5_command
38699 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
38701 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
38702 \ ******************************\
38703 \ RC5_ComputeNewRC5word \
38704 \ ******************************\
38706 MOV &BASE,2(PSP) \ save variable BASE before use
38707 MOV TOS,0(PSP) \ save TOS before use
38708 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
38709 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
38710 \ ******************************\
38711 \ RC5_ComputeC6bit \
38712 \ ******************************\
38713 BIT #$4000,IP \ test /C6 bit in IP
38714 0= IF BIS #$40,TOS \ set C6 bit in S
38715 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
38716 \ ******************************\
38717 \ RC5_CommandByteIsDone \ RC5_code --
38718 \ ******************************\
38720 \ ------------------------------\
38721 \ Display IR_RC5 code \
38722 \ ------------------------------\
38723 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
38724 \ ------------------------------\
38725 LO2HI \ switch from assembler to FORTH
38726 ['] LCD_CLEAR IS CR \ redirects CR
38727 ['] LCD_WrC IS EMIT \ redirects EMIT
38728 $10 BASE ! \ change BASE to hexadecimal
38729 CR ." $" 2 U.R \ print IR_RC5 code
38730 ['] (CR) IS CR \ restore CR
38731 ['] (EMIT) IS EMIT \ restore EMIT
38732 HI2LO \ switch from FORTH to assembler
38733 \ ------------------------------\
38734 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
38735 \ ------------------------------\
38736 MOV @PSP+,&BASE \ restore variable BASE
38737 RETI \ CPU is ON, GIE is OFF
38742 \ ------------------------------\
38743 \ TB0CTL = %0000 0010 1001 0100\$3C0
38744 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38745 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38746 \ -- \ID input divider \ 10 = /4
38747 \ -- \MC Mode Control \ 01 = up to TB0CCR0
38748 \ - \TBCLR TimerB Clear
38751 \ --------------------------------\\
38752 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38753 \ -- \CM Capture Mode
38758 \ --- \OUTMOD \ 011 = set/reset
38764 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
38766 \ ------------------------------\
38767 \ set TimerB to make 50kHz PWM \
38768 \ ------------------------------\
38769 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38770 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
38771 \ ------------------------------\
38772 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
38773 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
38774 \ ------------------------------\
38775 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38776 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
38777 \ ------------------------------\
38778 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38779 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
38780 \ ------------------------------\
38781 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
38782 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
38783 \ ------------------------------\
38784 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
38785 \ ------------------------------\
38786 \ set TimerB to generate PWM for LCD_Vo
38787 \ ------------------------------\
38788 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
38789 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
38790 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38791 \ ------------------------------\
38792 BIS.B #LCDVo,&LCDVo_DIR \
38793 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
38794 \ ------------------------------\
38795 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38796 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38797 \ ------------------------------\
38798 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38799 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38800 \ ------------------------------\
38801 \ WDT interval init part \
38802 \ ------------------------------\
38803 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
38804 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
38805 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
38806 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
38807 \ ------------------------------\
38809 \ ------------------------------\
38810 BIS.B #RC5,&IR_IE \ enable RC5_Int
38811 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38812 \ ------------------------------\
38813 \ init interrupt vectors
38814 \ ------------------------------\
38815 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
38816 MOV #RC5_INT,&IR_Vec \ init interrupt vector
38817 \ ------------------------------\
38818 \ define LPM mode for ACCEPT \
38819 \ ------------------------------\
38820 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38821 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38822 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38824 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
38826 \ ------------------------------\
38828 \ ------------------------------\
38829 $03E8 20_US \ 1- wait 20 ms
38830 $03 TOP_LCD \ 2- send DB5=DB4=1
38831 $CD 20_US \ 3- wait 4,1 ms
38832 $03 TOP_LCD \ 4- send again DB5=DB4=1
38833 $5 20_US \ 5- wait 0,1 ms
38834 $03 TOP_LCD \ 6- send again again DB5=DB4=1
38835 $2 20_US \ wait 40 us = LCD cycle
38836 $02 TOP_LCD \ 7- send DB5=1 DB4=0
38837 $2 20_US \ wait 40 us = LCD cycle
38838 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38839 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38840 LCD_Clear \ 10- "LCD_Clear"
38841 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38842 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38843 LCD_Clear \ 10- "LCD_Clear"
38844 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38845 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38847 ['] (CR) IS CR \ ' (CR) is CR
38848 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
38850 ." RC5toLCD is running. Type STOP to quit"
38851 \ NOECHO \ uncomment to run this app without terminal connexion
38852 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
38853 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
38857 : STOP \ stops multitasking, must to be used before downloading app
38858 ['] (WARM) IS WARM \ remove START app from FORTH init process
38859 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
38867 CODE MAX \ n1 n2 -- n3 signed maximum
38868 CMP @PSP,TOS \ n2-n1
38869 S< ?GOTO FW1 \ n2<n1
38875 CODE MIN \ n1 n2 -- n3 signed minimum
38876 CMP @PSP,TOS \ n2-n1
38877 S< ?GOTO BW1 \ n2<n1
38883 : U.R \ u n -- display u unsigned in n width (n >= 2)
38885 R> OVER - 0 MAX SPACES TYPE
38889 CODE 20_US \ n -- n * 20 us
38890 BEGIN \ 3 cycles loop + 6~
38891 \ MOV #5,W \ 3 MCLK = 1 MHz
38892 \ MOV #23,W \ 3 MCLK = 4 MHz
38893 MOV #51,W \ 3 MCLK = 8 MHz
38894 \ MOV #104,W \ 3 MCLK = 16 MHz
38895 \ MOV #158,W \ 3 MCLK = 24 MHz
38896 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
38906 CODE TOP_LCD \ LCD Sample
38907 \ \ if write : %xxxxWWWW --
38908 \ \ if read : -- %0000RRRR
38909 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38910 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38911 0= IF \ write LCD bits pattern
38912 AND.B #LCD_DB,TOS \
38913 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38914 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38917 THEN \ read LCD bits pattern
38920 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38921 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38922 AND.B #LCD_DB,TOS \
38927 CODE LCD_W \ byte -- write byte to LCD
38929 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
38930 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
38931 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38932 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38933 COLON \ high level word starts here
38934 TOP_LCD 2 20_US \ write high nibble first
38939 CODE LCD_WrC \ char -- Write Char
38940 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38945 CODE LCD_WrF \ func -- Write Fonction
38946 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38952 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
38957 $02 LCD_WrF 100 20_us
38961 \ : LCD_Entry_set $04 OR LCD_WrF ;
38963 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
38965 \ : LCD_Display_Shift $10 OR LCD_WrF ;
38967 \ : LCD_Fn_Set $20 OR LCD_WrF ;
38969 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
38971 \ : LCD_Goto $80 OR LCD_WrF ;
38973 \ CODE LCD_R \ -- byte read byte from LCD
38974 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38975 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38976 \ COLON \ starts a FORTH word
38977 \ TOP_LCD 2 20_us \ -- %0000HHHH
38978 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
38979 \ HI2LO \ switch from FORTH to assembler
38980 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
38981 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
38982 \ MOV @RSP+,IP \ restore IP saved by COLON
38987 \ CODE LCD_RdS \ -- status Read Status
38988 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38993 \ CODE LCD_RdC \ -- char Read Char
38994 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38999 \ -------------+------+------+------+------++---+---+---+---+---------+
39000 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
39001 \ -------------+------+------+------+------++---+---+---+---+---------+
39002 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
39003 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
39004 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
39005 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
39006 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
39007 \ -------------+------+------+------+------++---+---+---+---+---------+
39010 \ ******************************\
39011 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39012 \ ******************************\
39013 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
39014 \ ------------------------------\
39015 \ define LPM mode for ACCEPT \
39016 \ ------------------------------\
39017 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39018 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39019 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39020 BIT.B #SW2,&SW2_IN \ test switch S2
39021 0= IF \ case of switch S2 pressed
39022 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
39024 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
39027 BIT.B #SW1,&SW1_IN \ test switch S1 input
39028 0= IF \ case of Switch S1 pressed
39029 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
39031 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
39035 RETI \ CPU is ON, GIE is OFF
39040 \ ------------------------------\
39041 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39042 \ ******************************\
39043 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39044 \ ******************************\
39045 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39046 \ \ SMclock = 8|16|24 MHz
39047 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
39048 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
39049 \ \ SR(9)=new Toggle bit memory (ADD on)
39050 \ ------------------------------\
39051 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
39052 \ ------------------------------\
39053 \ define LPM mode for ACCEPT \
39054 \ ------------------------------\
39055 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39056 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39057 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39058 \ ------------------------------\
39059 \ RC5_FirstStartBitHalfCycle: \
39060 \ ------------------------------\
39061 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
39062 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
39063 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
39064 MOV #1778,X \ RC5_Period in us
39065 MOV #14,W \ count of loop
39067 \ ------------------------------\
39068 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
39069 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
39070 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
39071 \ RC5_Compute_3/4_Period: \ |
39072 RRUM #1,X \ X=1/2 cycle |
39076 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
39077 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
39079 \ ------------------------------\
39080 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
39081 \ ------------------------------\
39082 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39083 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
39084 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39085 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39086 SUB #1,W \ decrement count loop
39087 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
39088 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39089 0<> WHILE \ ----> out of loop ----+
39090 \ RC5_compute_7/4_Time_out: \ |
39091 ADD X,Y \ | out of bound = 7/4 period
39092 \ RC5_WaitHalfCycleP1.2_IFG: \ |
39094 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
39095 0>= IF \ | if cycle time out of bound
39096 BIC #$30,&TA0CTL \ | stop timer_A0
39097 RETI \ | then quit to do nothing
39099 \ ------------------------------\ |
39100 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
39102 MOV &TA0R,X \ | | get new RC5_period value
39103 REPEAT \ ----> loop back --+ |
39104 \ ------------------------------\ |
39105 \ RC5_SampleEndOf: \ <---------------------+
39106 \ ------------------------------\
39107 BIC #$30,&TA0CTL \ stop timer_A0
39108 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
39109 \ ******************************\
39110 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39111 \ ******************************\
39112 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
39113 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
39114 XOR IP,X \ (new XOR old) Toggle bit (13)
39115 BIT #BIT13,X \ X(13) = New_RC5_command
39116 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
39118 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
39119 \ ******************************\
39120 \ RC5_ComputeNewRC5word \
39121 \ ******************************\
39123 MOV &BASE,2(PSP) \ save variable BASE before use
39124 MOV TOS,0(PSP) \ save TOS before use
39125 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
39126 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
39127 \ ******************************\
39128 \ RC5_ComputeC6bit \
39129 \ ******************************\
39130 BIT #$4000,IP \ test /C6 bit in IP
39131 0= IF BIS #$40,TOS \ set C6 bit in S
39132 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
39133 \ ******************************\
39134 \ RC5_CommandByteIsDone \ RC5_code --
39135 \ ******************************\
39137 \ ------------------------------\
39138 \ Display IR_RC5 code \
39139 \ ------------------------------\
39140 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
39141 \ ------------------------------\
39142 LO2HI \ switch from assembler to FORTH
39143 ['] LCD_CLEAR IS CR \ redirects CR
39144 ['] LCD_WrC IS EMIT \ redirects EMIT
39145 $10 BASE ! \ change BASE to hexadecimal
39146 CR ." $" 2 U.R \ print IR_RC5 code
39147 ['] (CR) IS CR \ restore CR
39148 ['] (EMIT) IS EMIT \ restore EMIT
39149 HI2LO \ switch from FORTH to assembler
39150 \ ------------------------------\
39151 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
39152 \ ------------------------------\
39153 MOV @PSP+,&BASE \ restore variable BASE
39154 RETI \ CPU is ON, GIE is OFF
39159 \ ------------------------------\
39160 \ TB0CTL = %0000 0010 1001 0100\$3C0
39161 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39162 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39163 \ -- \ID input divider \ 10 = /4
39164 \ -- \MC Mode Control \ 01 = up to TB0CCR0
39165 \ - \TBCLR TimerB Clear
39168 \ --------------------------------\\
39169 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39170 \ -- \CM Capture Mode
39175 \ --- \OUTMOD \ 011 = set/reset
39181 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
39183 \ ------------------------------\
39184 \ set TimerB to make 50kHz PWM \
39185 \ ------------------------------\
39186 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39187 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
39188 \ ------------------------------\
39189 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39190 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
39191 \ ------------------------------\
39192 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39193 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
39194 \ ------------------------------\
39195 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39196 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
39197 \ ------------------------------\
39198 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39199 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
39200 \ ------------------------------\
39201 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
39202 \ ------------------------------\
39203 \ set TimerB to generate PWM for LCD_Vo
39204 \ ------------------------------\
39205 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
39206 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
39207 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39208 \ ------------------------------\
39209 BIS.B #LCDVo,&LCDVo_DIR \
39210 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
39211 \ ------------------------------\
39212 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39213 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39214 \ ------------------------------\
39215 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39216 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39217 \ ------------------------------\
39218 \ WDT interval init part \
39219 \ ------------------------------\
39220 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
39221 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
39222 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
39223 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
39224 \ ------------------------------\
39226 \ ------------------------------\
39227 BIS.B #RC5,&IR_IE \ enable RC5_Int
39228 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39229 \ ------------------------------\
39230 \ init interrupt vectors
39231 \ ------------------------------\
39232 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
39233 MOV #RC5_INT,&IR_Vec \ init interrupt vector
39234 \ ------------------------------\
39235 \ define LPM mode for ACCEPT \
39236 \ ------------------------------\
39237 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39238 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39239 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39241 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
39243 \ ------------------------------\
39245 \ ------------------------------\
39246 $03E8 20_US \ 1- wait 20 ms
39247 $03 TOP_LCD \ 2- send DB5=DB4=1
39248 $CD 20_US \ 3- wait 4,1 ms
39249 $03 TOP_LCD \ 4- send again DB5=DB4=1
39250 $5 20_US \ 5- wait 0,1 ms
39251 $03 TOP_LCD \ 6- send again again DB5=DB4=1
39252 $2 20_US \ wait 40 us = LCD cycle
39253 $02 TOP_LCD \ 7- send DB5=1 DB4=0
39254 $2 20_US \ wait 40 us = LCD cycle
39255 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39256 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39257 LCD_Clear \ 10- "LCD_Clear"
39258 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39259 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39260 LCD_Clear \ 10- "LCD_Clear"
39261 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
39262 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
39264 ['] (CR) IS CR \ ' (CR) is CR
39265 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
39267 ." RC5toLCD is running. Type STOP to quit"
39268 \ NOECHO \ uncomment to run this app without terminal connexion
39269 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
39270 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
39274 : STOP \ stops multitasking, must to be used before downloading app
39275 ['] (WARM) IS WARM \ remove START app from FORTH init process
39276 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
39284 CODE MAX \ n1 n2 -- n3 signed maximum
39285 CMP @PSP,TOS \ n2-n1
39286 S< ?GOTO FW1 \ n2<n1
39292 CODE MIN \ n1 n2 -- n3 signed minimum
39293 CMP @PSP,TOS \ n2-n1
39294 S< ?GOTO BW1 \ n2<n1
39300 : U.R \ u n -- display u unsigned in n width (n >= 2)
39302 R> OVER - 0 MAX SPACES TYPE
39306 CODE 20_US \ n -- n * 20 us
39307 BEGIN \ 3 cycles loop + 6~
39308 \ MOV #5,W \ 3 MCLK = 1 MHz
39309 \ MOV #23,W \ 3 MCLK = 4 MHz
39310 MOV #51,W \ 3 MCLK = 8 MHz
39311 \ MOV #104,W \ 3 MCLK = 16 MHz
39312 \ MOV #158,W \ 3 MCLK = 24 MHz
39313 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
39323 CODE TOP_LCD \ LCD Sample
39324 \ \ if write : %xxxxWWWW --
39325 \ \ if read : -- %0000RRRR
39326 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39327 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39328 0= IF \ write LCD bits pattern
39329 AND.B #LCD_DB,TOS \
39330 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39331 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39334 THEN \ read LCD bits pattern
39337 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39338 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39339 AND.B #LCD_DB,TOS \
39344 CODE LCD_W \ byte -- write byte to LCD
39346 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
39347 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
39348 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39349 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39350 COLON \ high level word starts here
39351 TOP_LCD 2 20_US \ write high nibble first
39356 CODE LCD_WrC \ char -- Write Char
39357 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39362 CODE LCD_WrF \ func -- Write Fonction
39363 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39369 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
39374 $02 LCD_WrF 100 20_us
39378 \ : LCD_Entry_set $04 OR LCD_WrF ;
39380 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
39382 \ : LCD_Display_Shift $10 OR LCD_WrF ;
39384 \ : LCD_Fn_Set $20 OR LCD_WrF ;
39386 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
39388 \ : LCD_Goto $80 OR LCD_WrF ;
39390 \ CODE LCD_R \ -- byte read byte from LCD
39391 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39392 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39393 \ COLON \ starts a FORTH word
39394 \ TOP_LCD 2 20_us \ -- %0000HHHH
39395 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
39396 \ HI2LO \ switch from FORTH to assembler
39397 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
39398 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
39399 \ MOV @RSP+,IP \ restore IP saved by COLON
39404 \ CODE LCD_RdS \ -- status Read Status
39405 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39410 \ CODE LCD_RdC \ -- char Read Char
39411 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39416 \ -------------+------+------+------+------++---+---+---+---+---------+
39417 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
39418 \ -------------+------+------+------+------++---+---+---+---+---------+
39419 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
39420 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
39421 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
39422 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
39423 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
39424 \ -------------+------+------+------+------++---+---+---+---+---------+
39427 \ ******************************\
39428 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39429 \ ******************************\
39430 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
39431 \ ------------------------------\
39432 \ define LPM mode for ACCEPT \
39433 \ ------------------------------\
39434 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39435 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39436 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39437 BIT.B #SW2,&SW2_IN \ test switch S2
39438 0= IF \ case of switch S2 pressed
39439 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
39441 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
39444 BIT.B #SW1,&SW1_IN \ test switch S1 input
39445 0= IF \ case of Switch S1 pressed
39446 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
39448 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
39452 RETI \ CPU is ON, GIE is OFF
39457 \ ------------------------------\
39458 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39459 \ ******************************\
39460 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39461 \ ******************************\
39462 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39463 \ \ SMclock = 8|16|24 MHz
39464 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
39465 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
39466 \ \ SR(9)=new Toggle bit memory (ADD on)
39467 \ ------------------------------\
39468 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
39469 \ ------------------------------\
39470 \ define LPM mode for ACCEPT \
39471 \ ------------------------------\
39472 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39473 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39474 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39475 \ ------------------------------\
39476 \ RC5_FirstStartBitHalfCycle: \
39477 \ ------------------------------\
39478 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
39479 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
39480 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
39481 MOV #1778,X \ RC5_Period in us
39482 MOV #14,W \ count of loop
39484 \ ------------------------------\
39485 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
39486 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
39487 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
39488 \ RC5_Compute_3/4_Period: \ |
39489 RRUM #1,X \ X=1/2 cycle |
39493 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
39494 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
39496 \ ------------------------------\
39497 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
39498 \ ------------------------------\
39499 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39500 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
39501 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39502 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39503 SUB #1,W \ decrement count loop
39504 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
39505 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39506 0<> WHILE \ ----> out of loop ----+
39507 \ RC5_compute_7/4_Time_out: \ |
39508 ADD X,Y \ | out of bound = 7/4 period
39509 \ RC5_WaitHalfCycleP1.2_IFG: \ |
39511 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
39512 0>= IF \ | if cycle time out of bound
39513 BIC #$30,&TA0CTL \ | stop timer_A0
39514 RETI \ | then quit to do nothing
39516 \ ------------------------------\ |
39517 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
39519 MOV &TA0R,X \ | | get new RC5_period value
39520 REPEAT \ ----> loop back --+ |
39521 \ ------------------------------\ |
39522 \ RC5_SampleEndOf: \ <---------------------+
39523 \ ------------------------------\
39524 BIC #$30,&TA0CTL \ stop timer_A0
39525 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
39526 \ ******************************\
39527 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39528 \ ******************************\
39529 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
39530 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
39531 XOR IP,X \ (new XOR old) Toggle bit (13)
39532 BIT #BIT13,X \ X(13) = New_RC5_command
39533 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
39535 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
39536 \ ******************************\
39537 \ RC5_ComputeNewRC5word \
39538 \ ******************************\
39540 MOV &BASE,2(PSP) \ save variable BASE before use
39541 MOV TOS,0(PSP) \ save TOS before use
39542 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
39543 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
39544 \ ******************************\
39545 \ RC5_ComputeC6bit \
39546 \ ******************************\
39547 BIT #$4000,IP \ test /C6 bit in IP
39548 0= IF BIS #$40,TOS \ set C6 bit in S
39549 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
39550 \ ******************************\
39551 \ RC5_CommandByteIsDone \ RC5_code --
39552 \ ******************************\
39554 \ ------------------------------\
39555 \ Display IR_RC5 code \
39556 \ ------------------------------\
39557 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
39558 \ ------------------------------\
39559 LO2HI \ switch from assembler to FORTH
39560 ['] LCD_CLEAR IS CR \ redirects CR
39561 ['] LCD_WrC IS EMIT \ redirects EMIT
39562 $10 BASE ! \ change BASE to hexadecimal
39563 CR ." $" 2 U.R \ print IR_RC5 code
39564 ['] (CR) IS CR \ restore CR
39565 ['] (EMIT) IS EMIT \ restore EMIT
39566 HI2LO \ switch from FORTH to assembler
39567 \ ------------------------------\
39568 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
39569 \ ------------------------------\
39570 MOV @PSP+,&BASE \ restore variable BASE
39571 RETI \ CPU is ON, GIE is OFF
39576 \ ------------------------------\
39577 \ TB0CTL = %0000 0010 1001 0100\$3C0
39578 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39579 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39580 \ -- \ID input divider \ 10 = /4
39581 \ -- \MC Mode Control \ 01 = up to TB0CCR0
39582 \ - \TBCLR TimerB Clear
39585 \ --------------------------------\\
39586 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39587 \ -- \CM Capture Mode
39592 \ --- \OUTMOD \ 011 = set/reset
39598 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
39600 \ ------------------------------\
39601 \ set TimerB to make 50kHz PWM \
39602 \ ------------------------------\
39603 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39604 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
39605 \ ------------------------------\
39606 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
39607 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
39608 \ ------------------------------\
39609 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39610 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
39611 \ ------------------------------\
39612 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39613 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
39614 \ ------------------------------\
39615 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
39616 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
39617 \ ------------------------------\
39618 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
39619 \ ------------------------------\
39620 \ set TimerB to generate PWM for LCD_Vo
39621 \ ------------------------------\
39622 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
39623 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
39624 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39625 \ ------------------------------\
39626 BIS.B #LCDVo,&LCDVo_DIR \
39627 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
39628 \ ------------------------------\
39629 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39630 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39631 \ ------------------------------\
39632 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39633 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39634 \ ------------------------------\
39635 \ WDT interval init part \
39636 \ ------------------------------\
39637 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
39638 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
39639 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
39640 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
39641 \ ------------------------------\
39643 \ ------------------------------\
39644 BIS.B #RC5,&IR_IE \ enable RC5_Int
39645 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39646 \ ------------------------------\
39647 \ init interrupt vectors
39648 \ ------------------------------\
39649 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
39650 MOV #RC5_INT,&IR_Vec \ init interrupt vector
39651 \ ------------------------------\
39652 \ define LPM mode for ACCEPT \
39653 \ ------------------------------\
39654 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39655 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39656 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39658 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
39660 \ ------------------------------\
39662 \ ------------------------------\
39663 $03E8 20_US \ 1- wait 20 ms
39664 $03 TOP_LCD \ 2- send DB5=DB4=1
39665 $CD 20_US \ 3- wait 4,1 ms
39666 $03 TOP_LCD \ 4- send again DB5=DB4=1
39667 $5 20_US \ 5- wait 0,1 ms
39668 $03 TOP_LCD \ 6- send again again DB5=DB4=1
39669 $2 20_US \ wait 40 us = LCD cycle
39670 $02 TOP_LCD \ 7- send DB5=1 DB4=0
39671 $2 20_US \ wait 40 us = LCD cycle
39672 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39673 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39674 LCD_Clear \ 10- "LCD_Clear"
39675 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39676 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39677 LCD_Clear \ 10- "LCD_Clear"
39678 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
39679 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
39681 ['] (CR) IS CR \ ' (CR) is CR
39682 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
39684 ." RC5toLCD is running. Type STOP to quit"
39685 \ NOECHO \ uncomment to run this app without terminal connexion
39686 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
39687 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
39691 : STOP \ stops multitasking, must to be used before downloading app
39692 ['] (WARM) IS WARM \ remove START app from FORTH init process
39693 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
39701 CODE MAX \ n1 n2 -- n3 signed maximum
39702 CMP @PSP,TOS \ n2-n1
39703 S< ?GOTO FW1 \ n2<n1
39709 CODE MIN \ n1 n2 -- n3 signed minimum
39710 CMP @PSP,TOS \ n2-n1
39711 S< ?GOTO BW1 \ n2<n1
39717 : U.R \ u n -- display u unsigned in n width (n >= 2)
39719 R> OVER - 0 MAX SPACES TYPE
39723 CODE 20_US \ n -- n * 20 us
39724 BEGIN \ 3 cycles loop + 6~
39725 \ MOV #5,W \ 3 MCLK = 1 MHz
39726 \ MOV #23,W \ 3 MCLK = 4 MHz
39727 MOV #51,W \ 3 MCLK = 8 MHz
39728 \ MOV #104,W \ 3 MCLK = 16 MHz
39729 \ MOV #158,W \ 3 MCLK = 24 MHz
39730 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
39740 CODE TOP_LCD \ LCD Sample
39741 \ \ if write : %xxxxWWWW --
39742 \ \ if read : -- %0000RRRR
39743 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39744 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39745 0= IF \ write LCD bits pattern
39746 AND.B #LCD_DB,TOS \
39747 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39748 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39751 THEN \ read LCD bits pattern
39754 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39755 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39756 AND.B #LCD_DB,TOS \
39761 CODE LCD_W \ byte -- write byte to LCD
39763 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
39764 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
39765 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39766 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39767 COLON \ high level word starts here
39768 TOP_LCD 2 20_US \ write high nibble first
39773 CODE LCD_WrC \ char -- Write Char
39774 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39779 CODE LCD_WrF \ func -- Write Fonction
39780 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39786 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
39791 $02 LCD_WrF 100 20_us
39795 \ : LCD_Entry_set $04 OR LCD_WrF ;
39797 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
39799 \ : LCD_Display_Shift $10 OR LCD_WrF ;
39801 \ : LCD_Fn_Set $20 OR LCD_WrF ;
39803 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
39805 \ : LCD_Goto $80 OR LCD_WrF ;
39807 \ CODE LCD_R \ -- byte read byte from LCD
39808 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39809 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39810 \ COLON \ starts a FORTH word
39811 \ TOP_LCD 2 20_us \ -- %0000HHHH
39812 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
39813 \ HI2LO \ switch from FORTH to assembler
39814 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
39815 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
39816 \ MOV @RSP+,IP \ restore IP saved by COLON
39821 \ CODE LCD_RdS \ -- status Read Status
39822 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39827 \ CODE LCD_RdC \ -- char Read Char
39828 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39833 \ -------------+------+------+------+------++---+---+---+---+---------+
39834 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
39835 \ -------------+------+------+------+------++---+---+---+---+---------+
39836 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
39837 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
39838 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
39839 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
39840 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
39841 \ -------------+------+------+------+------++---+---+---+---+---------+
39844 \ ******************************\
39845 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39846 \ ******************************\
39847 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
39848 \ ------------------------------\
39849 \ define LPM mode for ACCEPT \
39850 \ ------------------------------\
39851 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39852 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39853 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39854 BIT.B #SW2,&SW2_IN \ test switch S2
39855 0= IF \ case of switch S2 pressed
39856 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
39858 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
39861 BIT.B #SW1,&SW1_IN \ test switch S1 input
39862 0= IF \ case of Switch S1 pressed
39863 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
39865 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
39869 RETI \ CPU is ON, GIE is OFF
39874 \ ------------------------------\
39875 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39876 \ ******************************\
39877 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39878 \ ******************************\
39879 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39880 \ \ SMclock = 8|16|24 MHz
39881 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
39882 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
39883 \ \ SR(9)=new Toggle bit memory (ADD on)
39884 \ ------------------------------\
39885 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
39886 \ ------------------------------\
39887 \ define LPM mode for ACCEPT \
39888 \ ------------------------------\
39889 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39890 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39891 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39892 \ ------------------------------\
39893 \ RC5_FirstStartBitHalfCycle: \
39894 \ ------------------------------\
39895 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
39896 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
39897 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
39898 MOV #1778,X \ RC5_Period in us
39899 MOV #14,W \ count of loop
39901 \ ------------------------------\
39902 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
39903 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
39904 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
39905 \ RC5_Compute_3/4_Period: \ |
39906 RRUM #1,X \ X=1/2 cycle |
39910 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
39911 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
39913 \ ------------------------------\
39914 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
39915 \ ------------------------------\
39916 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39917 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
39918 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39919 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39920 SUB #1,W \ decrement count loop
39921 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
39922 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39923 0<> WHILE \ ----> out of loop ----+
39924 \ RC5_compute_7/4_Time_out: \ |
39925 ADD X,Y \ | out of bound = 7/4 period
39926 \ RC5_WaitHalfCycleP1.2_IFG: \ |
39928 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
39929 0>= IF \ | if cycle time out of bound
39930 BIC #$30,&TA0CTL \ | stop timer_A0
39931 RETI \ | then quit to do nothing
39933 \ ------------------------------\ |
39934 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
39936 MOV &TA0R,X \ | | get new RC5_period value
39937 REPEAT \ ----> loop back --+ |
39938 \ ------------------------------\ |
39939 \ RC5_SampleEndOf: \ <---------------------+
39940 \ ------------------------------\
39941 BIC #$30,&TA0CTL \ stop timer_A0
39942 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
39943 \ ******************************\
39944 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39945 \ ******************************\
39946 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
39947 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
39948 XOR IP,X \ (new XOR old) Toggle bit (13)
39949 BIT #BIT13,X \ X(13) = New_RC5_command
39950 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
39952 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
39953 \ ******************************\
39954 \ RC5_ComputeNewRC5word \
39955 \ ******************************\
39957 MOV &BASE,2(PSP) \ save variable BASE before use
39958 MOV TOS,0(PSP) \ save TOS before use
39959 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
39960 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
39961 \ ******************************\
39962 \ RC5_ComputeC6bit \
39963 \ ******************************\
39964 BIT #$4000,IP \ test /C6 bit in IP
39965 0= IF BIS #$40,TOS \ set C6 bit in S
39966 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
39967 \ ******************************\
39968 \ RC5_CommandByteIsDone \ RC5_code --
39969 \ ******************************\
39971 \ ------------------------------\
39972 \ Display IR_RC5 code \
39973 \ ------------------------------\
39974 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
39975 \ ------------------------------\
39976 LO2HI \ switch from assembler to FORTH
39977 ['] LCD_CLEAR IS CR \ redirects CR
39978 ['] LCD_WrC IS EMIT \ redirects EMIT
39979 $10 BASE ! \ change BASE to hexadecimal
39980 CR ." $" 2 U.R \ print IR_RC5 code
39981 ['] (CR) IS CR \ restore CR
39982 ['] (EMIT) IS EMIT \ restore EMIT
39983 HI2LO \ switch from FORTH to assembler
39984 \ ------------------------------\
39985 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
39986 \ ------------------------------\
39987 MOV @PSP+,&BASE \ restore variable BASE
39988 RETI \ CPU is ON, GIE is OFF
39993 \ ------------------------------\
39994 \ TB0CTL = %0000 0010 1001 0100\$3C0
39995 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39996 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39997 \ -- \ID input divider \ 10 = /4
39998 \ -- \MC Mode Control \ 01 = up to TB0CCR0
39999 \ - \TBCLR TimerB Clear
40002 \ --------------------------------\\
40003 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40004 \ -- \CM Capture Mode
40009 \ --- \OUTMOD \ 011 = set/reset
40015 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
40017 \ ------------------------------\
40018 \ set TimerB to make 50kHz PWM \
40019 \ ------------------------------\
40020 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40021 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
40022 \ ------------------------------\
40023 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40024 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
40025 \ ------------------------------\
40026 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40027 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
40028 \ ------------------------------\
40029 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40030 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
40031 \ ------------------------------\
40032 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40033 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
40034 \ ------------------------------\
40035 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
40036 \ ------------------------------\
40037 \ set TimerB to generate PWM for LCD_Vo
40038 \ ------------------------------\
40039 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
40040 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
40041 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40042 \ ------------------------------\
40043 BIS.B #LCDVo,&LCDVo_DIR \
40044 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
40045 \ ------------------------------\
40046 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40047 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40048 \ ------------------------------\
40049 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40050 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40051 \ ------------------------------\
40052 \ WDT interval init part \
40053 \ ------------------------------\
40054 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
40055 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
40056 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
40057 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
40058 \ ------------------------------\
40060 \ ------------------------------\
40061 BIS.B #RC5,&IR_IE \ enable RC5_Int
40062 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40063 \ ------------------------------\
40064 \ init interrupt vectors
40065 \ ------------------------------\
40066 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
40067 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40068 \ ------------------------------\
40069 \ define LPM mode for ACCEPT \
40070 \ ------------------------------\
40071 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40072 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40073 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40075 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
40077 \ ------------------------------\
40079 \ ------------------------------\
40080 $03E8 20_US \ 1- wait 20 ms
40081 $03 TOP_LCD \ 2- send DB5=DB4=1
40082 $CD 20_US \ 3- wait 4,1 ms
40083 $03 TOP_LCD \ 4- send again DB5=DB4=1
40084 $5 20_US \ 5- wait 0,1 ms
40085 $03 TOP_LCD \ 6- send again again DB5=DB4=1
40086 $2 20_US \ wait 40 us = LCD cycle
40087 $02 TOP_LCD \ 7- send DB5=1 DB4=0
40088 $2 20_US \ wait 40 us = LCD cycle
40089 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40090 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40091 LCD_Clear \ 10- "LCD_Clear"
40092 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40093 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40094 LCD_Clear \ 10- "LCD_Clear"
40095 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40096 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40098 ['] (CR) IS CR \ ' (CR) is CR
40099 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
40101 ." RC5toLCD is running. Type STOP to quit"
40102 \ NOECHO \ uncomment to run this app without terminal connexion
40103 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
40104 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
40108 : STOP \ stops multitasking, must to be used before downloading app
40109 ['] (WARM) IS WARM \ remove START app from FORTH init process
40110 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
40118 CODE MAX \ n1 n2 -- n3 signed maximum
40119 CMP @PSP,TOS \ n2-n1
40120 S< ?GOTO FW1 \ n2<n1
40126 CODE MIN \ n1 n2 -- n3 signed minimum
40127 CMP @PSP,TOS \ n2-n1
40128 S< ?GOTO BW1 \ n2<n1
40134 : U.R \ u n -- display u unsigned in n width (n >= 2)
40136 R> OVER - 0 MAX SPACES TYPE
40140 CODE 20_US \ n -- n * 20 us
40141 BEGIN \ 3 cycles loop + 6~
40142 \ MOV #5,W \ 3 MCLK = 1 MHz
40143 \ MOV #23,W \ 3 MCLK = 4 MHz
40144 MOV #51,W \ 3 MCLK = 8 MHz
40145 \ MOV #104,W \ 3 MCLK = 16 MHz
40146 \ MOV #158,W \ 3 MCLK = 24 MHz
40147 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
40157 CODE TOP_LCD \ LCD Sample
40158 \ \ if write : %xxxxWWWW --
40159 \ \ if read : -- %0000RRRR
40160 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40161 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40162 0= IF \ write LCD bits pattern
40163 AND.B #LCD_DB,TOS \
40164 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40165 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40168 THEN \ read LCD bits pattern
40171 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40172 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40173 AND.B #LCD_DB,TOS \
40178 CODE LCD_W \ byte -- write byte to LCD
40180 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
40181 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
40182 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40183 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40184 COLON \ high level word starts here
40185 TOP_LCD 2 20_US \ write high nibble first
40190 CODE LCD_WrC \ char -- Write Char
40191 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40196 CODE LCD_WrF \ func -- Write Fonction
40197 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40203 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
40208 $02 LCD_WrF 100 20_us
40212 \ : LCD_Entry_set $04 OR LCD_WrF ;
40214 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
40216 \ : LCD_Display_Shift $10 OR LCD_WrF ;
40218 \ : LCD_Fn_Set $20 OR LCD_WrF ;
40220 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
40222 \ : LCD_Goto $80 OR LCD_WrF ;
40224 \ CODE LCD_R \ -- byte read byte from LCD
40225 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40226 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40227 \ COLON \ starts a FORTH word
40228 \ TOP_LCD 2 20_us \ -- %0000HHHH
40229 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
40230 \ HI2LO \ switch from FORTH to assembler
40231 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
40232 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
40233 \ MOV @RSP+,IP \ restore IP saved by COLON
40238 \ CODE LCD_RdS \ -- status Read Status
40239 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40244 \ CODE LCD_RdC \ -- char Read Char
40245 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40250 \ -------------+------+------+------+------++---+---+---+---+---------+
40251 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
40252 \ -------------+------+------+------+------++---+---+---+---+---------+
40253 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
40254 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
40255 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
40256 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
40257 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
40258 \ -------------+------+------+------+------++---+---+---+---+---------+
40261 \ ******************************\
40262 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40263 \ ******************************\
40264 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
40265 \ ------------------------------\
40266 \ define LPM mode for ACCEPT \
40267 \ ------------------------------\
40268 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40269 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40270 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40271 BIT.B #SW2,&SW2_IN \ test switch S2
40272 0= IF \ case of switch S2 pressed
40273 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
40275 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
40278 BIT.B #SW1,&SW1_IN \ test switch S1 input
40279 0= IF \ case of Switch S1 pressed
40280 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
40282 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
40286 RETI \ CPU is ON, GIE is OFF
40291 \ ------------------------------\
40292 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40293 \ ******************************\
40294 ASM RC5_INT \ wake up on Px.RC5 change interrupt
40295 \ ******************************\
40296 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40297 \ \ SMclock = 8|16|24 MHz
40298 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
40299 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
40300 \ \ SR(9)=new Toggle bit memory (ADD on)
40301 \ ------------------------------\
40302 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
40303 \ ------------------------------\
40304 \ define LPM mode for ACCEPT \
40305 \ ------------------------------\
40306 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40307 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40308 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40309 \ ------------------------------\
40310 \ RC5_FirstStartBitHalfCycle: \
40311 \ ------------------------------\
40312 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
40313 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
40314 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
40315 MOV #1778,X \ RC5_Period in us
40316 MOV #14,W \ count of loop
40318 \ ------------------------------\
40319 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
40320 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
40321 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
40322 \ RC5_Compute_3/4_Period: \ |
40323 RRUM #1,X \ X=1/2 cycle |
40327 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
40328 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
40330 \ ------------------------------\
40331 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
40332 \ ------------------------------\
40333 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40334 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
40335 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40336 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40337 SUB #1,W \ decrement count loop
40338 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
40339 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40340 0<> WHILE \ ----> out of loop ----+
40341 \ RC5_compute_7/4_Time_out: \ |
40342 ADD X,Y \ | out of bound = 7/4 period
40343 \ RC5_WaitHalfCycleP1.2_IFG: \ |
40345 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
40346 0>= IF \ | if cycle time out of bound
40347 BIC #$30,&TA0CTL \ | stop timer_A0
40348 RETI \ | then quit to do nothing
40350 \ ------------------------------\ |
40351 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
40353 MOV &TA0R,X \ | | get new RC5_period value
40354 REPEAT \ ----> loop back --+ |
40355 \ ------------------------------\ |
40356 \ RC5_SampleEndOf: \ <---------------------+
40357 \ ------------------------------\
40358 BIC #$30,&TA0CTL \ stop timer_A0
40359 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
40360 \ ******************************\
40361 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
40362 \ ******************************\
40363 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
40364 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
40365 XOR IP,X \ (new XOR old) Toggle bit (13)
40366 BIT #BIT13,X \ X(13) = New_RC5_command
40367 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
40369 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
40370 \ ******************************\
40371 \ RC5_ComputeNewRC5word \
40372 \ ******************************\
40374 MOV &BASE,2(PSP) \ save variable BASE before use
40375 MOV TOS,0(PSP) \ save TOS before use
40376 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
40377 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
40378 \ ******************************\
40379 \ RC5_ComputeC6bit \
40380 \ ******************************\
40381 BIT #$4000,IP \ test /C6 bit in IP
40382 0= IF BIS #$40,TOS \ set C6 bit in S
40383 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
40384 \ ******************************\
40385 \ RC5_CommandByteIsDone \ RC5_code --
40386 \ ******************************\
40388 \ ------------------------------\
40389 \ Display IR_RC5 code \
40390 \ ------------------------------\
40391 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
40392 \ ------------------------------\
40393 LO2HI \ switch from assembler to FORTH
40394 ['] LCD_CLEAR IS CR \ redirects CR
40395 ['] LCD_WrC IS EMIT \ redirects EMIT
40396 $10 BASE ! \ change BASE to hexadecimal
40397 CR ." $" 2 U.R \ print IR_RC5 code
40398 ['] (CR) IS CR \ restore CR
40399 ['] (EMIT) IS EMIT \ restore EMIT
40400 HI2LO \ switch from FORTH to assembler
40401 \ ------------------------------\
40402 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
40403 \ ------------------------------\
40404 MOV @PSP+,&BASE \ restore variable BASE
40405 RETI \ CPU is ON, GIE is OFF
40410 \ ------------------------------\
40411 \ TB0CTL = %0000 0010 1001 0100\$3C0
40412 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40413 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40414 \ -- \ID input divider \ 10 = /4
40415 \ -- \MC Mode Control \ 01 = up to TB0CCR0
40416 \ - \TBCLR TimerB Clear
40419 \ --------------------------------\\
40420 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40421 \ -- \CM Capture Mode
40426 \ --- \OUTMOD \ 011 = set/reset
40432 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
40434 \ ------------------------------\
40435 \ set TimerB to make 50kHz PWM \
40436 \ ------------------------------\
40437 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40438 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
40439 \ ------------------------------\
40440 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40441 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
40442 \ ------------------------------\
40443 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40444 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
40445 \ ------------------------------\
40446 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40447 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
40448 \ ------------------------------\
40449 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40450 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
40451 \ ------------------------------\
40452 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
40453 \ ------------------------------\
40454 \ set TimerB to generate PWM for LCD_Vo
40455 \ ------------------------------\
40456 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
40457 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
40458 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40459 \ ------------------------------\
40460 BIS.B #LCDVo,&LCDVo_DIR \
40461 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
40462 \ ------------------------------\
40463 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40464 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40465 \ ------------------------------\
40466 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40467 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40468 \ ------------------------------\
40469 \ WDT interval init part \
40470 \ ------------------------------\
40471 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
40472 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
40473 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
40474 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
40475 \ ------------------------------\
40477 \ ------------------------------\
40478 BIS.B #RC5,&IR_IE \ enable RC5_Int
40479 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40480 \ ------------------------------\
40481 \ init interrupt vectors
40482 \ ------------------------------\
40483 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
40484 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40485 \ ------------------------------\
40486 \ define LPM mode for ACCEPT \
40487 \ ------------------------------\
40488 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40489 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40490 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40492 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
40494 \ ------------------------------\
40496 \ ------------------------------\
40497 $03E8 20_US \ 1- wait 20 ms
40498 $03 TOP_LCD \ 2- send DB5=DB4=1
40499 $CD 20_US \ 3- wait 4,1 ms
40500 $03 TOP_LCD \ 4- send again DB5=DB4=1
40501 $5 20_US \ 5- wait 0,1 ms
40502 $03 TOP_LCD \ 6- send again again DB5=DB4=1
40503 $2 20_US \ wait 40 us = LCD cycle
40504 $02 TOP_LCD \ 7- send DB5=1 DB4=0
40505 $2 20_US \ wait 40 us = LCD cycle
40506 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40507 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40508 LCD_Clear \ 10- "LCD_Clear"
40509 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40510 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40511 LCD_Clear \ 10- "LCD_Clear"
40512 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40513 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40515 ['] (CR) IS CR \ ' (CR) is CR
40516 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
40518 ." RC5toLCD is running. Type STOP to quit"
40519 \ NOECHO \ uncomment to run this app without terminal connexion
40520 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
40521 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
40525 : STOP \ stops multitasking, must to be used before downloading app
40526 ['] (WARM) IS WARM \ remove START app from FORTH init process
40527 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
40535 CODE MAX \ n1 n2 -- n3 signed maximum
40536 CMP @PSP,TOS \ n2-n1
40537 S< ?GOTO FW1 \ n2<n1
40543 CODE MIN \ n1 n2 -- n3 signed minimum
40544 CMP @PSP,TOS \ n2-n1
40545 S< ?GOTO BW1 \ n2<n1
40551 : U.R \ u n -- display u unsigned in n width (n >= 2)
40553 R> OVER - 0 MAX SPACES TYPE
40557 CODE 20_US \ n -- n * 20 us
40558 BEGIN \ 3 cycles loop + 6~
40559 \ MOV #5,W \ 3 MCLK = 1 MHz
40560 \ MOV #23,W \ 3 MCLK = 4 MHz
40561 MOV #51,W \ 3 MCLK = 8 MHz
40562 \ MOV #104,W \ 3 MCLK = 16 MHz
40563 \ MOV #158,W \ 3 MCLK = 24 MHz
40564 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
40574 CODE TOP_LCD \ LCD Sample
40575 \ \ if write : %xxxxWWWW --
40576 \ \ if read : -- %0000RRRR
40577 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40578 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40579 0= IF \ write LCD bits pattern
40580 AND.B #LCD_DB,TOS \
40581 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40582 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40585 THEN \ read LCD bits pattern
40588 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40589 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40590 AND.B #LCD_DB,TOS \
40595 CODE LCD_W \ byte -- write byte to LCD
40597 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
40598 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
40599 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40600 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40601 COLON \ high level word starts here
40602 TOP_LCD 2 20_US \ write high nibble first
40607 CODE LCD_WrC \ char -- Write Char
40608 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40613 CODE LCD_WrF \ func -- Write Fonction
40614 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40620 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
40625 $02 LCD_WrF 100 20_us
40629 \ : LCD_Entry_set $04 OR LCD_WrF ;
40631 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
40633 \ : LCD_Display_Shift $10 OR LCD_WrF ;
40635 \ : LCD_Fn_Set $20 OR LCD_WrF ;
40637 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
40639 \ : LCD_Goto $80 OR LCD_WrF ;
40641 \ CODE LCD_R \ -- byte read byte from LCD
40642 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40643 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40644 \ COLON \ starts a FORTH word
40645 \ TOP_LCD 2 20_us \ -- %0000HHHH
40646 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
40647 \ HI2LO \ switch from FORTH to assembler
40648 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
40649 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
40650 \ MOV @RSP+,IP \ restore IP saved by COLON
40655 \ CODE LCD_RdS \ -- status Read Status
40656 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40661 \ CODE LCD_RdC \ -- char Read Char
40662 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40667 \ -------------+------+------+------+------++---+---+---+---+---------+
40668 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
40669 \ -------------+------+------+------+------++---+---+---+---+---------+
40670 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
40671 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
40672 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
40673 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
40674 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
40675 \ -------------+------+------+------+------++---+---+---+---+---------+
40678 \ ******************************\
40679 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40680 \ ******************************\
40681 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
40682 \ ------------------------------\
40683 \ define LPM mode for ACCEPT \
40684 \ ------------------------------\
40685 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40686 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40687 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40688 BIT.B #SW2,&SW2_IN \ test switch S2
40689 0= IF \ case of switch S2 pressed
40690 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
40692 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
40695 BIT.B #SW1,&SW1_IN \ test switch S1 input
40696 0= IF \ case of Switch S1 pressed
40697 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
40699 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
40703 RETI \ CPU is ON, GIE is OFF
40708 \ ------------------------------\
40709 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40710 \ ******************************\
40711 ASM RC5_INT \ wake up on Px.RC5 change interrupt
40712 \ ******************************\
40713 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40714 \ \ SMclock = 8|16|24 MHz
40715 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
40716 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
40717 \ \ SR(9)=new Toggle bit memory (ADD on)
40718 \ ------------------------------\
40719 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
40720 \ ------------------------------\
40721 \ define LPM mode for ACCEPT \
40722 \ ------------------------------\
40723 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40724 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40725 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40726 \ ------------------------------\
40727 \ RC5_FirstStartBitHalfCycle: \
40728 \ ------------------------------\
40729 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
40730 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
40731 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
40732 MOV #1778,X \ RC5_Period in us
40733 MOV #14,W \ count of loop
40735 \ ------------------------------\
40736 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
40737 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
40738 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
40739 \ RC5_Compute_3/4_Period: \ |
40740 RRUM #1,X \ X=1/2 cycle |
40744 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
40745 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
40747 \ ------------------------------\
40748 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
40749 \ ------------------------------\
40750 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40751 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
40752 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40753 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40754 SUB #1,W \ decrement count loop
40755 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
40756 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40757 0<> WHILE \ ----> out of loop ----+
40758 \ RC5_compute_7/4_Time_out: \ |
40759 ADD X,Y \ | out of bound = 7/4 period
40760 \ RC5_WaitHalfCycleP1.2_IFG: \ |
40762 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
40763 0>= IF \ | if cycle time out of bound
40764 BIC #$30,&TA0CTL \ | stop timer_A0
40765 RETI \ | then quit to do nothing
40767 \ ------------------------------\ |
40768 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
40770 MOV &TA0R,X \ | | get new RC5_period value
40771 REPEAT \ ----> loop back --+ |
40772 \ ------------------------------\ |
40773 \ RC5_SampleEndOf: \ <---------------------+
40774 \ ------------------------------\
40775 BIC #$30,&TA0CTL \ stop timer_A0
40776 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
40777 \ ******************************\
40778 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
40779 \ ******************************\
40780 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
40781 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
40782 XOR IP,X \ (new XOR old) Toggle bit (13)
40783 BIT #BIT13,X \ X(13) = New_RC5_command
40784 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
40786 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
40787 \ ******************************\
40788 \ RC5_ComputeNewRC5word \
40789 \ ******************************\
40791 MOV &BASE,2(PSP) \ save variable BASE before use
40792 MOV TOS,0(PSP) \ save TOS before use
40793 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
40794 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
40795 \ ******************************\
40796 \ RC5_ComputeC6bit \
40797 \ ******************************\
40798 BIT #$4000,IP \ test /C6 bit in IP
40799 0= IF BIS #$40,TOS \ set C6 bit in S
40800 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
40801 \ ******************************\
40802 \ RC5_CommandByteIsDone \ RC5_code --
40803 \ ******************************\
40805 \ ------------------------------\
40806 \ Display IR_RC5 code \
40807 \ ------------------------------\
40808 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
40809 \ ------------------------------\
40810 LO2HI \ switch from assembler to FORTH
40811 ['] LCD_CLEAR IS CR \ redirects CR
40812 ['] LCD_WrC IS EMIT \ redirects EMIT
40813 $10 BASE ! \ change BASE to hexadecimal
40814 CR ." $" 2 U.R \ print IR_RC5 code
40815 ['] (CR) IS CR \ restore CR
40816 ['] (EMIT) IS EMIT \ restore EMIT
40817 HI2LO \ switch from FORTH to assembler
40818 \ ------------------------------\
40819 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
40820 \ ------------------------------\
40821 MOV @PSP+,&BASE \ restore variable BASE
40822 RETI \ CPU is ON, GIE is OFF
40827 \ ------------------------------\
40828 \ TB0CTL = %0000 0010 1001 0100\$3C0
40829 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40830 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40831 \ -- \ID input divider \ 10 = /4
40832 \ -- \MC Mode Control \ 01 = up to TB0CCR0
40833 \ - \TBCLR TimerB Clear
40836 \ --------------------------------\\
40837 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40838 \ -- \CM Capture Mode
40843 \ --- \OUTMOD \ 011 = set/reset
40849 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
40851 \ ------------------------------\
40852 \ set TimerB to make 50kHz PWM \
40853 \ ------------------------------\
40854 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40855 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
40856 \ ------------------------------\
40857 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
40858 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
40859 \ ------------------------------\
40860 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40861 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
40862 \ ------------------------------\
40863 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40864 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
40865 \ ------------------------------\
40866 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
40867 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
40868 \ ------------------------------\
40869 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
40870 \ ------------------------------\
40871 \ set TimerB to generate PWM for LCD_Vo
40872 \ ------------------------------\
40873 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
40874 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
40875 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40876 \ ------------------------------\
40877 BIS.B #LCDVo,&LCDVo_DIR \
40878 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
40879 \ ------------------------------\
40880 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40881 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40882 \ ------------------------------\
40883 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40884 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40885 \ ------------------------------\
40886 \ WDT interval init part \
40887 \ ------------------------------\
40888 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
40889 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
40890 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
40891 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
40892 \ ------------------------------\
40894 \ ------------------------------\
40895 BIS.B #RC5,&IR_IE \ enable RC5_Int
40896 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40897 \ ------------------------------\
40898 \ init interrupt vectors
40899 \ ------------------------------\
40900 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
40901 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40902 \ ------------------------------\
40903 \ define LPM mode for ACCEPT \
40904 \ ------------------------------\
40905 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40906 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40907 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40909 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
40911 \ ------------------------------\
40913 \ ------------------------------\
40914 $03E8 20_US \ 1- wait 20 ms
40915 $03 TOP_LCD \ 2- send DB5=DB4=1
40916 $CD 20_US \ 3- wait 4,1 ms
40917 $03 TOP_LCD \ 4- send again DB5=DB4=1
40918 $5 20_US \ 5- wait 0,1 ms
40919 $03 TOP_LCD \ 6- send again again DB5=DB4=1
40920 $2 20_US \ wait 40 us = LCD cycle
40921 $02 TOP_LCD \ 7- send DB5=1 DB4=0
40922 $2 20_US \ wait 40 us = LCD cycle
40923 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40924 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40925 LCD_Clear \ 10- "LCD_Clear"
40926 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40927 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40928 LCD_Clear \ 10- "LCD_Clear"
40929 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40930 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40932 ['] (CR) IS CR \ ' (CR) is CR
40933 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
40935 ." RC5toLCD is running. Type STOP to quit"
40936 \ NOECHO \ uncomment to run this app without terminal connexion
40937 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
40938 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
40942 : STOP \ stops multitasking, must to be used before downloading app
40943 ['] (WARM) IS WARM \ remove START app from FORTH init process
40944 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
40952 CODE MAX \ n1 n2 -- n3 signed maximum
40953 CMP @PSP,TOS \ n2-n1
40954 S< ?GOTO FW1 \ n2<n1
40960 CODE MIN \ n1 n2 -- n3 signed minimum
40961 CMP @PSP,TOS \ n2-n1
40962 S< ?GOTO BW1 \ n2<n1
40968 : U.R \ u n -- display u unsigned in n width (n >= 2)
40970 R> OVER - 0 MAX SPACES TYPE
40974 CODE 20_US \ n -- n * 20 us
40975 BEGIN \ 3 cycles loop + 6~
40976 \ MOV #5,W \ 3 MCLK = 1 MHz
40977 \ MOV #23,W \ 3 MCLK = 4 MHz
40978 MOV #51,W \ 3 MCLK = 8 MHz
40979 \ MOV #104,W \ 3 MCLK = 16 MHz
40980 \ MOV #158,W \ 3 MCLK = 24 MHz
40981 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
40991 CODE TOP_LCD \ LCD Sample
40992 \ \ if write : %xxxxWWWW --
40993 \ \ if read : -- %0000RRRR
40994 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40995 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40996 0= IF \ write LCD bits pattern
40997 AND.B #LCD_DB,TOS \
40998 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40999 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41002 THEN \ read LCD bits pattern
41005 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41006 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41007 AND.B #LCD_DB,TOS \
41012 CODE LCD_W \ byte -- write byte to LCD
41014 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
41015 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
41016 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41017 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41018 COLON \ high level word starts here
41019 TOP_LCD 2 20_US \ write high nibble first
41024 CODE LCD_WrC \ char -- Write Char
41025 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41030 CODE LCD_WrF \ func -- Write Fonction
41031 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41037 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
41042 $02 LCD_WrF 100 20_us
41046 \ : LCD_Entry_set $04 OR LCD_WrF ;
41048 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
41050 \ : LCD_Display_Shift $10 OR LCD_WrF ;
41052 \ : LCD_Fn_Set $20 OR LCD_WrF ;
41054 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
41056 \ : LCD_Goto $80 OR LCD_WrF ;
41058 \ CODE LCD_R \ -- byte read byte from LCD
41059 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41060 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41061 \ COLON \ starts a FORTH word
41062 \ TOP_LCD 2 20_us \ -- %0000HHHH
41063 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
41064 \ HI2LO \ switch from FORTH to assembler
41065 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
41066 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
41067 \ MOV @RSP+,IP \ restore IP saved by COLON
41072 \ CODE LCD_RdS \ -- status Read Status
41073 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41078 \ CODE LCD_RdC \ -- char Read Char
41079 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41084 \ -------------+------+------+------+------++---+---+---+---+---------+
41085 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
41086 \ -------------+------+------+------+------++---+---+---+---+---------+
41087 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
41088 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
41089 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
41090 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
41091 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
41092 \ -------------+------+------+------+------++---+---+---+---+---------+
41095 \ ******************************\
41096 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41097 \ ******************************\
41098 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
41099 \ ------------------------------\
41100 \ define LPM mode for ACCEPT \
41101 \ ------------------------------\
41102 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41103 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41104 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41105 BIT.B #SW2,&SW2_IN \ test switch S2
41106 0= IF \ case of switch S2 pressed
41107 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
41109 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
41112 BIT.B #SW1,&SW1_IN \ test switch S1 input
41113 0= IF \ case of Switch S1 pressed
41114 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
41116 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
41120 RETI \ CPU is ON, GIE is OFF
41125 \ ------------------------------\
41126 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41127 \ ******************************\
41128 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41129 \ ******************************\
41130 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41131 \ \ SMclock = 8|16|24 MHz
41132 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
41133 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
41134 \ \ SR(9)=new Toggle bit memory (ADD on)
41135 \ ------------------------------\
41136 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
41137 \ ------------------------------\
41138 \ define LPM mode for ACCEPT \
41139 \ ------------------------------\
41140 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41141 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41142 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41143 \ ------------------------------\
41144 \ RC5_FirstStartBitHalfCycle: \
41145 \ ------------------------------\
41146 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
41147 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
41148 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
41149 MOV #1778,X \ RC5_Period in us
41150 MOV #14,W \ count of loop
41152 \ ------------------------------\
41153 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
41154 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
41155 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
41156 \ RC5_Compute_3/4_Period: \ |
41157 RRUM #1,X \ X=1/2 cycle |
41161 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
41162 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
41164 \ ------------------------------\
41165 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
41166 \ ------------------------------\
41167 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41168 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
41169 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41170 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41171 SUB #1,W \ decrement count loop
41172 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
41173 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41174 0<> WHILE \ ----> out of loop ----+
41175 \ RC5_compute_7/4_Time_out: \ |
41176 ADD X,Y \ | out of bound = 7/4 period
41177 \ RC5_WaitHalfCycleP1.2_IFG: \ |
41179 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
41180 0>= IF \ | if cycle time out of bound
41181 BIC #$30,&TA0CTL \ | stop timer_A0
41182 RETI \ | then quit to do nothing
41184 \ ------------------------------\ |
41185 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
41187 MOV &TA0R,X \ | | get new RC5_period value
41188 REPEAT \ ----> loop back --+ |
41189 \ ------------------------------\ |
41190 \ RC5_SampleEndOf: \ <---------------------+
41191 \ ------------------------------\
41192 BIC #$30,&TA0CTL \ stop timer_A0
41193 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
41194 \ ******************************\
41195 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
41196 \ ******************************\
41197 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
41198 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
41199 XOR IP,X \ (new XOR old) Toggle bit (13)
41200 BIT #BIT13,X \ X(13) = New_RC5_command
41201 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
41203 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
41204 \ ******************************\
41205 \ RC5_ComputeNewRC5word \
41206 \ ******************************\
41208 MOV &BASE,2(PSP) \ save variable BASE before use
41209 MOV TOS,0(PSP) \ save TOS before use
41210 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
41211 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
41212 \ ******************************\
41213 \ RC5_ComputeC6bit \
41214 \ ******************************\
41215 BIT #$4000,IP \ test /C6 bit in IP
41216 0= IF BIS #$40,TOS \ set C6 bit in S
41217 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
41218 \ ******************************\
41219 \ RC5_CommandByteIsDone \ RC5_code --
41220 \ ******************************\
41222 \ ------------------------------\
41223 \ Display IR_RC5 code \
41224 \ ------------------------------\
41225 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
41226 \ ------------------------------\
41227 LO2HI \ switch from assembler to FORTH
41228 ['] LCD_CLEAR IS CR \ redirects CR
41229 ['] LCD_WrC IS EMIT \ redirects EMIT
41230 $10 BASE ! \ change BASE to hexadecimal
41231 CR ." $" 2 U.R \ print IR_RC5 code
41232 ['] (CR) IS CR \ restore CR
41233 ['] (EMIT) IS EMIT \ restore EMIT
41234 HI2LO \ switch from FORTH to assembler
41235 \ ------------------------------\
41236 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
41237 \ ------------------------------\
41238 MOV @PSP+,&BASE \ restore variable BASE
41239 RETI \ CPU is ON, GIE is OFF
41244 \ ------------------------------\
41245 \ TB0CTL = %0000 0010 1001 0100\$3C0
41246 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41247 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41248 \ -- \ID input divider \ 10 = /4
41249 \ -- \MC Mode Control \ 01 = up to TB0CCR0
41250 \ - \TBCLR TimerB Clear
41253 \ --------------------------------\\
41254 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41255 \ -- \CM Capture Mode
41260 \ --- \OUTMOD \ 011 = set/reset
41266 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
41268 \ ------------------------------\
41269 \ set TimerB to make 50kHz PWM \
41270 \ ------------------------------\
41271 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41272 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
41273 \ ------------------------------\
41274 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41275 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
41276 \ ------------------------------\
41277 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41278 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
41279 \ ------------------------------\
41280 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41281 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
41282 \ ------------------------------\
41283 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41284 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
41285 \ ------------------------------\
41286 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
41287 \ ------------------------------\
41288 \ set TimerB to generate PWM for LCD_Vo
41289 \ ------------------------------\
41290 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
41291 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
41292 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41293 \ ------------------------------\
41294 BIS.B #LCDVo,&LCDVo_DIR \
41295 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
41296 \ ------------------------------\
41297 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41298 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41299 \ ------------------------------\
41300 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41301 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41302 \ ------------------------------\
41303 \ WDT interval init part \
41304 \ ------------------------------\
41305 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
41306 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
41307 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
41308 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
41309 \ ------------------------------\
41311 \ ------------------------------\
41312 BIS.B #RC5,&IR_IE \ enable RC5_Int
41313 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41314 \ ------------------------------\
41315 \ init interrupt vectors
41316 \ ------------------------------\
41317 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
41318 MOV #RC5_INT,&IR_Vec \ init interrupt vector
41319 \ ------------------------------\
41320 \ define LPM mode for ACCEPT \
41321 \ ------------------------------\
41322 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41323 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41324 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41326 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
41328 \ ------------------------------\
41330 \ ------------------------------\
41331 $03E8 20_US \ 1- wait 20 ms
41332 $03 TOP_LCD \ 2- send DB5=DB4=1
41333 $CD 20_US \ 3- wait 4,1 ms
41334 $03 TOP_LCD \ 4- send again DB5=DB4=1
41335 $5 20_US \ 5- wait 0,1 ms
41336 $03 TOP_LCD \ 6- send again again DB5=DB4=1
41337 $2 20_US \ wait 40 us = LCD cycle
41338 $02 TOP_LCD \ 7- send DB5=1 DB4=0
41339 $2 20_US \ wait 40 us = LCD cycle
41340 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41341 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41342 LCD_Clear \ 10- "LCD_Clear"
41343 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41344 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41345 LCD_Clear \ 10- "LCD_Clear"
41346 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41347 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41349 ['] (CR) IS CR \ ' (CR) is CR
41350 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
41352 ." RC5toLCD is running. Type STOP to quit"
41353 \ NOECHO \ uncomment to run this app without terminal connexion
41354 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
41355 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
41359 : STOP \ stops multitasking, must to be used before downloading app
41360 ['] (WARM) IS WARM \ remove START app from FORTH init process
41361 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
41369 CODE MAX \ n1 n2 -- n3 signed maximum
41370 CMP @PSP,TOS \ n2-n1
41371 S< ?GOTO FW1 \ n2<n1
41377 CODE MIN \ n1 n2 -- n3 signed minimum
41378 CMP @PSP,TOS \ n2-n1
41379 S< ?GOTO BW1 \ n2<n1
41385 : U.R \ u n -- display u unsigned in n width (n >= 2)
41387 R> OVER - 0 MAX SPACES TYPE
41391 CODE 20_US \ n -- n * 20 us
41392 BEGIN \ 3 cycles loop + 6~
41393 \ MOV #5,W \ 3 MCLK = 1 MHz
41394 \ MOV #23,W \ 3 MCLK = 4 MHz
41395 MOV #51,W \ 3 MCLK = 8 MHz
41396 \ MOV #104,W \ 3 MCLK = 16 MHz
41397 \ MOV #158,W \ 3 MCLK = 24 MHz
41398 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
41408 CODE TOP_LCD \ LCD Sample
41409 \ \ if write : %xxxxWWWW --
41410 \ \ if read : -- %0000RRRR
41411 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41412 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41413 0= IF \ write LCD bits pattern
41414 AND.B #LCD_DB,TOS \
41415 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41416 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41419 THEN \ read LCD bits pattern
41422 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41423 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41424 AND.B #LCD_DB,TOS \
41429 CODE LCD_W \ byte -- write byte to LCD
41431 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
41432 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
41433 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41434 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41435 COLON \ high level word starts here
41436 TOP_LCD 2 20_US \ write high nibble first
41441 CODE LCD_WrC \ char -- Write Char
41442 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41447 CODE LCD_WrF \ func -- Write Fonction
41448 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41454 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
41459 $02 LCD_WrF 100 20_us
41463 \ : LCD_Entry_set $04 OR LCD_WrF ;
41465 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
41467 \ : LCD_Display_Shift $10 OR LCD_WrF ;
41469 \ : LCD_Fn_Set $20 OR LCD_WrF ;
41471 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
41473 \ : LCD_Goto $80 OR LCD_WrF ;
41475 \ CODE LCD_R \ -- byte read byte from LCD
41476 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41477 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41478 \ COLON \ starts a FORTH word
41479 \ TOP_LCD 2 20_us \ -- %0000HHHH
41480 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
41481 \ HI2LO \ switch from FORTH to assembler
41482 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
41483 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
41484 \ MOV @RSP+,IP \ restore IP saved by COLON
41489 \ CODE LCD_RdS \ -- status Read Status
41490 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41495 \ CODE LCD_RdC \ -- char Read Char
41496 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41501 \ -------------+------+------+------+------++---+---+---+---+---------+
41502 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
41503 \ -------------+------+------+------+------++---+---+---+---+---------+
41504 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
41505 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
41506 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
41507 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
41508 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
41509 \ -------------+------+------+------+------++---+---+---+---+---------+
41512 \ ******************************\
41513 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41514 \ ******************************\
41515 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
41516 \ ------------------------------\
41517 \ define LPM mode for ACCEPT \
41518 \ ------------------------------\
41519 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41520 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41521 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41522 BIT.B #SW2,&SW2_IN \ test switch S2
41523 0= IF \ case of switch S2 pressed
41524 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
41526 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
41529 BIT.B #SW1,&SW1_IN \ test switch S1 input
41530 0= IF \ case of Switch S1 pressed
41531 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
41533 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
41537 RETI \ CPU is ON, GIE is OFF
41542 \ ------------------------------\
41543 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41544 \ ******************************\
41545 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41546 \ ******************************\
41547 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41548 \ \ SMclock = 8|16|24 MHz
41549 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
41550 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
41551 \ \ SR(9)=new Toggle bit memory (ADD on)
41552 \ ------------------------------\
41553 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
41554 \ ------------------------------\
41555 \ define LPM mode for ACCEPT \
41556 \ ------------------------------\
41557 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41558 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41559 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41560 \ ------------------------------\
41561 \ RC5_FirstStartBitHalfCycle: \
41562 \ ------------------------------\
41563 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
41564 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
41565 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
41566 MOV #1778,X \ RC5_Period in us
41567 MOV #14,W \ count of loop
41569 \ ------------------------------\
41570 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
41571 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
41572 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
41573 \ RC5_Compute_3/4_Period: \ |
41574 RRUM #1,X \ X=1/2 cycle |
41578 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
41579 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
41581 \ ------------------------------\
41582 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
41583 \ ------------------------------\
41584 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41585 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
41586 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41587 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41588 SUB #1,W \ decrement count loop
41589 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
41590 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41591 0<> WHILE \ ----> out of loop ----+
41592 \ RC5_compute_7/4_Time_out: \ |
41593 ADD X,Y \ | out of bound = 7/4 period
41594 \ RC5_WaitHalfCycleP1.2_IFG: \ |
41596 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
41597 0>= IF \ | if cycle time out of bound
41598 BIC #$30,&TA0CTL \ | stop timer_A0
41599 RETI \ | then quit to do nothing
41601 \ ------------------------------\ |
41602 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
41604 MOV &TA0R,X \ | | get new RC5_period value
41605 REPEAT \ ----> loop back --+ |
41606 \ ------------------------------\ |
41607 \ RC5_SampleEndOf: \ <---------------------+
41608 \ ------------------------------\
41609 BIC #$30,&TA0CTL \ stop timer_A0
41610 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
41611 \ ******************************\
41612 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
41613 \ ******************************\
41614 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
41615 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
41616 XOR IP,X \ (new XOR old) Toggle bit (13)
41617 BIT #BIT13,X \ X(13) = New_RC5_command
41618 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
41620 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
41621 \ ******************************\
41622 \ RC5_ComputeNewRC5word \
41623 \ ******************************\
41625 MOV &BASE,2(PSP) \ save variable BASE before use
41626 MOV TOS,0(PSP) \ save TOS before use
41627 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
41628 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
41629 \ ******************************\
41630 \ RC5_ComputeC6bit \
41631 \ ******************************\
41632 BIT #$4000,IP \ test /C6 bit in IP
41633 0= IF BIS #$40,TOS \ set C6 bit in S
41634 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
41635 \ ******************************\
41636 \ RC5_CommandByteIsDone \ RC5_code --
41637 \ ******************************\
41639 \ ------------------------------\
41640 \ Display IR_RC5 code \
41641 \ ------------------------------\
41642 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
41643 \ ------------------------------\
41644 LO2HI \ switch from assembler to FORTH
41645 ['] LCD_CLEAR IS CR \ redirects CR
41646 ['] LCD_WrC IS EMIT \ redirects EMIT
41647 $10 BASE ! \ change BASE to hexadecimal
41648 CR ." $" 2 U.R \ print IR_RC5 code
41649 ['] (CR) IS CR \ restore CR
41650 ['] (EMIT) IS EMIT \ restore EMIT
41651 HI2LO \ switch from FORTH to assembler
41652 \ ------------------------------\
41653 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
41654 \ ------------------------------\
41655 MOV @PSP+,&BASE \ restore variable BASE
41656 RETI \ CPU is ON, GIE is OFF
41661 \ ------------------------------\
41662 \ TB0CTL = %0000 0010 1001 0100\$3C0
41663 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41664 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41665 \ -- \ID input divider \ 10 = /4
41666 \ -- \MC Mode Control \ 01 = up to TB0CCR0
41667 \ - \TBCLR TimerB Clear
41670 \ --------------------------------\\
41671 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41672 \ -- \CM Capture Mode
41677 \ --- \OUTMOD \ 011 = set/reset
41683 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
41685 \ ------------------------------\
41686 \ set TimerB to make 50kHz PWM \
41687 \ ------------------------------\
41688 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41689 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
41690 \ ------------------------------\
41691 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
41692 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
41693 \ ------------------------------\
41694 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41695 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
41696 \ ------------------------------\
41697 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41698 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
41699 \ ------------------------------\
41700 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
41701 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
41702 \ ------------------------------\
41703 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
41704 \ ------------------------------\
41705 \ set TimerB to generate PWM for LCD_Vo
41706 \ ------------------------------\
41707 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
41708 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
41709 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41710 \ ------------------------------\
41711 BIS.B #LCDVo,&LCDVo_DIR \
41712 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
41713 \ ------------------------------\
41714 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41715 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41716 \ ------------------------------\
41717 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41718 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41719 \ ------------------------------\
41720 \ WDT interval init part \
41721 \ ------------------------------\
41722 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
41723 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
41724 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
41725 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
41726 \ ------------------------------\
41728 \ ------------------------------\
41729 BIS.B #RC5,&IR_IE \ enable RC5_Int
41730 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41731 \ ------------------------------\
41732 \ init interrupt vectors
41733 \ ------------------------------\
41734 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
41735 MOV #RC5_INT,&IR_Vec \ init interrupt vector
41736 \ ------------------------------\
41737 \ define LPM mode for ACCEPT \
41738 \ ------------------------------\
41739 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41740 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41741 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41743 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
41745 \ ------------------------------\
41747 \ ------------------------------\
41748 $03E8 20_US \ 1- wait 20 ms
41749 $03 TOP_LCD \ 2- send DB5=DB4=1
41750 $CD 20_US \ 3- wait 4,1 ms
41751 $03 TOP_LCD \ 4- send again DB5=DB4=1
41752 $5 20_US \ 5- wait 0,1 ms
41753 $03 TOP_LCD \ 6- send again again DB5=DB4=1
41754 $2 20_US \ wait 40 us = LCD cycle
41755 $02 TOP_LCD \ 7- send DB5=1 DB4=0
41756 $2 20_US \ wait 40 us = LCD cycle
41757 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41758 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41759 LCD_Clear \ 10- "LCD_Clear"
41760 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41761 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41762 LCD_Clear \ 10- "LCD_Clear"
41763 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41764 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41766 ['] (CR) IS CR \ ' (CR) is CR
41767 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
41769 ." RC5toLCD is running. Type STOP to quit"
41770 \ NOECHO \ uncomment to run this app without terminal connexion
41771 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
41772 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
41776 : STOP \ stops multitasking, must to be used before downloading app
41777 ['] (WARM) IS WARM \ remove START app from FORTH init process
41778 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
41786 CODE MAX \ n1 n2 -- n3 signed maximum
41787 CMP @PSP,TOS \ n2-n1
41788 S< ?GOTO FW1 \ n2<n1
41794 CODE MIN \ n1 n2 -- n3 signed minimum
41795 CMP @PSP,TOS \ n2-n1
41796 S< ?GOTO BW1 \ n2<n1
41802 : U.R \ u n -- display u unsigned in n width (n >= 2)
41804 R> OVER - 0 MAX SPACES TYPE
41808 CODE 20_US \ n -- n * 20 us
41809 BEGIN \ 3 cycles loop + 6~
41810 \ MOV #5,W \ 3 MCLK = 1 MHz
41811 \ MOV #23,W \ 3 MCLK = 4 MHz
41812 MOV #51,W \ 3 MCLK = 8 MHz
41813 \ MOV #104,W \ 3 MCLK = 16 MHz
41814 \ MOV #158,W \ 3 MCLK = 24 MHz
41815 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
41825 CODE TOP_LCD \ LCD Sample
41826 \ \ if write : %xxxxWWWW --
41827 \ \ if read : -- %0000RRRR
41828 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41829 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41830 0= IF \ write LCD bits pattern
41831 AND.B #LCD_DB,TOS \
41832 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41833 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41836 THEN \ read LCD bits pattern
41839 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41840 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41841 AND.B #LCD_DB,TOS \
41846 CODE LCD_W \ byte -- write byte to LCD
41848 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
41849 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
41850 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41851 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41852 COLON \ high level word starts here
41853 TOP_LCD 2 20_US \ write high nibble first
41858 CODE LCD_WrC \ char -- Write Char
41859 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41864 CODE LCD_WrF \ func -- Write Fonction
41865 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41871 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
41876 $02 LCD_WrF 100 20_us
41880 \ : LCD_Entry_set $04 OR LCD_WrF ;
41882 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
41884 \ : LCD_Display_Shift $10 OR LCD_WrF ;
41886 \ : LCD_Fn_Set $20 OR LCD_WrF ;
41888 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
41890 \ : LCD_Goto $80 OR LCD_WrF ;
41892 \ CODE LCD_R \ -- byte read byte from LCD
41893 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41894 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41895 \ COLON \ starts a FORTH word
41896 \ TOP_LCD 2 20_us \ -- %0000HHHH
41897 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
41898 \ HI2LO \ switch from FORTH to assembler
41899 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
41900 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
41901 \ MOV @RSP+,IP \ restore IP saved by COLON
41906 \ CODE LCD_RdS \ -- status Read Status
41907 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41912 \ CODE LCD_RdC \ -- char Read Char
41913 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41918 \ -------------+------+------+------+------++---+---+---+---+---------+
41919 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
41920 \ -------------+------+------+------+------++---+---+---+---+---------+
41921 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
41922 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
41923 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
41924 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
41925 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
41926 \ -------------+------+------+------+------++---+---+---+---+---------+
41929 \ ******************************\
41930 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41931 \ ******************************\
41932 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
41933 \ ------------------------------\
41934 \ define LPM mode for ACCEPT \
41935 \ ------------------------------\
41936 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41937 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41938 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41939 BIT.B #SW2,&SW2_IN \ test switch S2
41940 0= IF \ case of switch S2 pressed
41941 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
41943 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
41946 BIT.B #SW1,&SW1_IN \ test switch S1 input
41947 0= IF \ case of Switch S1 pressed
41948 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
41950 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
41954 RETI \ CPU is ON, GIE is OFF
41959 \ ------------------------------\
41960 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41961 \ ******************************\
41962 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41963 \ ******************************\
41964 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41965 \ \ SMclock = 8|16|24 MHz
41966 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
41967 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
41968 \ \ SR(9)=new Toggle bit memory (ADD on)
41969 \ ------------------------------\
41970 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
41971 \ ------------------------------\
41972 \ define LPM mode for ACCEPT \
41973 \ ------------------------------\
41974 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41975 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41976 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41977 \ ------------------------------\
41978 \ RC5_FirstStartBitHalfCycle: \
41979 \ ------------------------------\
41980 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
41981 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
41982 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
41983 MOV #1778,X \ RC5_Period in us
41984 MOV #14,W \ count of loop
41986 \ ------------------------------\
41987 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
41988 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
41989 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
41990 \ RC5_Compute_3/4_Period: \ |
41991 RRUM #1,X \ X=1/2 cycle |
41995 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
41996 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
41998 \ ------------------------------\
41999 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
42000 \ ------------------------------\
42001 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42002 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
42003 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42004 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42005 SUB #1,W \ decrement count loop
42006 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
42007 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42008 0<> WHILE \ ----> out of loop ----+
42009 \ RC5_compute_7/4_Time_out: \ |
42010 ADD X,Y \ | out of bound = 7/4 period
42011 \ RC5_WaitHalfCycleP1.2_IFG: \ |
42013 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
42014 0>= IF \ | if cycle time out of bound
42015 BIC #$30,&TA0CTL \ | stop timer_A0
42016 RETI \ | then quit to do nothing
42018 \ ------------------------------\ |
42019 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
42021 MOV &TA0R,X \ | | get new RC5_period value
42022 REPEAT \ ----> loop back --+ |
42023 \ ------------------------------\ |
42024 \ RC5_SampleEndOf: \ <---------------------+
42025 \ ------------------------------\
42026 BIC #$30,&TA0CTL \ stop timer_A0
42027 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
42028 \ ******************************\
42029 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42030 \ ******************************\
42031 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
42032 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
42033 XOR IP,X \ (new XOR old) Toggle bit (13)
42034 BIT #BIT13,X \ X(13) = New_RC5_command
42035 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
42037 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
42038 \ ******************************\
42039 \ RC5_ComputeNewRC5word \
42040 \ ******************************\
42042 MOV &BASE,2(PSP) \ save variable BASE before use
42043 MOV TOS,0(PSP) \ save TOS before use
42044 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
42045 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
42046 \ ******************************\
42047 \ RC5_ComputeC6bit \
42048 \ ******************************\
42049 BIT #$4000,IP \ test /C6 bit in IP
42050 0= IF BIS #$40,TOS \ set C6 bit in S
42051 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
42052 \ ******************************\
42053 \ RC5_CommandByteIsDone \ RC5_code --
42054 \ ******************************\
42056 \ ------------------------------\
42057 \ Display IR_RC5 code \
42058 \ ------------------------------\
42059 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
42060 \ ------------------------------\
42061 LO2HI \ switch from assembler to FORTH
42062 ['] LCD_CLEAR IS CR \ redirects CR
42063 ['] LCD_WrC IS EMIT \ redirects EMIT
42064 $10 BASE ! \ change BASE to hexadecimal
42065 CR ." $" 2 U.R \ print IR_RC5 code
42066 ['] (CR) IS CR \ restore CR
42067 ['] (EMIT) IS EMIT \ restore EMIT
42068 HI2LO \ switch from FORTH to assembler
42069 \ ------------------------------\
42070 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
42071 \ ------------------------------\
42072 MOV @PSP+,&BASE \ restore variable BASE
42073 RETI \ CPU is ON, GIE is OFF
42078 \ ------------------------------\
42079 \ TB0CTL = %0000 0010 1001 0100\$3C0
42080 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42081 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42082 \ -- \ID input divider \ 10 = /4
42083 \ -- \MC Mode Control \ 01 = up to TB0CCR0
42084 \ - \TBCLR TimerB Clear
42087 \ --------------------------------\\
42088 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42089 \ -- \CM Capture Mode
42094 \ --- \OUTMOD \ 011 = set/reset
42100 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
42102 \ ------------------------------\
42103 \ set TimerB to make 50kHz PWM \
42104 \ ------------------------------\
42105 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42106 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
42107 \ ------------------------------\
42108 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42109 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
42110 \ ------------------------------\
42111 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42112 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
42113 \ ------------------------------\
42114 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42115 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
42116 \ ------------------------------\
42117 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42118 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
42119 \ ------------------------------\
42120 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
42121 \ ------------------------------\
42122 \ set TimerB to generate PWM for LCD_Vo
42123 \ ------------------------------\
42124 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
42125 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
42126 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42127 \ ------------------------------\
42128 BIS.B #LCDVo,&LCDVo_DIR \
42129 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
42130 \ ------------------------------\
42131 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42132 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42133 \ ------------------------------\
42134 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42135 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42136 \ ------------------------------\
42137 \ WDT interval init part \
42138 \ ------------------------------\
42139 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
42140 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
42141 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
42142 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
42143 \ ------------------------------\
42145 \ ------------------------------\
42146 BIS.B #RC5,&IR_IE \ enable RC5_Int
42147 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42148 \ ------------------------------\
42149 \ init interrupt vectors
42150 \ ------------------------------\
42151 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
42152 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42153 \ ------------------------------\
42154 \ define LPM mode for ACCEPT \
42155 \ ------------------------------\
42156 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42157 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42158 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42160 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
42162 \ ------------------------------\
42164 \ ------------------------------\
42165 $03E8 20_US \ 1- wait 20 ms
42166 $03 TOP_LCD \ 2- send DB5=DB4=1
42167 $CD 20_US \ 3- wait 4,1 ms
42168 $03 TOP_LCD \ 4- send again DB5=DB4=1
42169 $5 20_US \ 5- wait 0,1 ms
42170 $03 TOP_LCD \ 6- send again again DB5=DB4=1
42171 $2 20_US \ wait 40 us = LCD cycle
42172 $02 TOP_LCD \ 7- send DB5=1 DB4=0
42173 $2 20_US \ wait 40 us = LCD cycle
42174 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42175 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
42176 LCD_Clear \ 10- "LCD_Clear"
42177 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
42178 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
42179 LCD_Clear \ 10- "LCD_Clear"
42180 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
42181 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
42183 ['] (CR) IS CR \ ' (CR) is CR
42184 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
42186 ." RC5toLCD is running. Type STOP to quit"
42187 \ NOECHO \ uncomment to run this app without terminal connexion
42188 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
42189 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
42193 : STOP \ stops multitasking, must to be used before downloading app
42194 ['] (WARM) IS WARM \ remove START app from FORTH init process
42195 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
42203 CODE MAX \ n1 n2 -- n3 signed maximum
42204 CMP @PSP,TOS \ n2-n1
42205 S< ?GOTO FW1 \ n2<n1
42211 CODE MIN \ n1 n2 -- n3 signed minimum
42212 CMP @PSP,TOS \ n2-n1
42213 S< ?GOTO BW1 \ n2<n1
42219 : U.R \ u n -- display u unsigned in n width (n >= 2)
42221 R> OVER - 0 MAX SPACES TYPE
42225 CODE 20_US \ n -- n * 20 us
42226 BEGIN \ 3 cycles loop + 6~
42227 \ MOV #5,W \ 3 MCLK = 1 MHz
42228 \ MOV #23,W \ 3 MCLK = 4 MHz
42229 MOV #51,W \ 3 MCLK = 8 MHz
42230 \ MOV #104,W \ 3 MCLK = 16 MHz
42231 \ MOV #158,W \ 3 MCLK = 24 MHz
42232 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
42242 CODE TOP_LCD \ LCD Sample
42243 \ \ if write : %xxxxWWWW --
42244 \ \ if read : -- %0000RRRR
42245 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
42246 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
42247 0= IF \ write LCD bits pattern
42248 AND.B #LCD_DB,TOS \
42249 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
42250 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42253 THEN \ read LCD bits pattern
42256 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42257 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
42258 AND.B #LCD_DB,TOS \
42263 CODE LCD_W \ byte -- write byte to LCD
42265 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
42266 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
42267 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
42268 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
42269 COLON \ high level word starts here
42270 TOP_LCD 2 20_US \ write high nibble first
42275 CODE LCD_WrC \ char -- Write Char
42276 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42281 CODE LCD_WrF \ func -- Write Fonction
42282 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42288 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
42293 $02 LCD_WrF 100 20_us
42297 \ : LCD_Entry_set $04 OR LCD_WrF ;
42299 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
42301 \ : LCD_Display_Shift $10 OR LCD_WrF ;
42303 \ : LCD_Fn_Set $20 OR LCD_WrF ;
42305 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
42307 \ : LCD_Goto $80 OR LCD_WrF ;
42309 \ CODE LCD_R \ -- byte read byte from LCD
42310 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
42311 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
42312 \ COLON \ starts a FORTH word
42313 \ TOP_LCD 2 20_us \ -- %0000HHHH
42314 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
42315 \ HI2LO \ switch from FORTH to assembler
42316 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
42317 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
42318 \ MOV @RSP+,IP \ restore IP saved by COLON
42323 \ CODE LCD_RdS \ -- status Read Status
42324 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42329 \ CODE LCD_RdC \ -- char Read Char
42330 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42335 \ -------------+------+------+------+------++---+---+---+---+---------+
42336 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
42337 \ -------------+------+------+------+------++---+---+---+---+---------+
42338 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
42339 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
42340 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
42341 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
42342 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
42343 \ -------------+------+------+------+------++---+---+---+---+---------+
42346 \ ******************************\
42347 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
42348 \ ******************************\
42349 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
42350 \ ------------------------------\
42351 \ define LPM mode for ACCEPT \
42352 \ ------------------------------\
42353 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42354 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42355 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42356 BIT.B #SW2,&SW2_IN \ test switch S2
42357 0= IF \ case of switch S2 pressed
42358 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
42360 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
42363 BIT.B #SW1,&SW1_IN \ test switch S1 input
42364 0= IF \ case of Switch S1 pressed
42365 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
42367 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
42371 RETI \ CPU is ON, GIE is OFF
42376 \ ------------------------------\
42377 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
42378 \ ******************************\
42379 ASM RC5_INT \ wake up on Px.RC5 change interrupt
42380 \ ******************************\
42381 \ \ in : SR(9)=old Toggle bit memory (ADD on)
42382 \ \ SMclock = 8|16|24 MHz
42383 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
42384 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
42385 \ \ SR(9)=new Toggle bit memory (ADD on)
42386 \ ------------------------------\
42387 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
42388 \ ------------------------------\
42389 \ define LPM mode for ACCEPT \
42390 \ ------------------------------\
42391 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42392 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42393 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42394 \ ------------------------------\
42395 \ RC5_FirstStartBitHalfCycle: \
42396 \ ------------------------------\
42397 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
42398 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
42399 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
42400 MOV #1778,X \ RC5_Period in us
42401 MOV #14,W \ count of loop
42403 \ ------------------------------\
42404 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
42405 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
42406 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
42407 \ RC5_Compute_3/4_Period: \ |
42408 RRUM #1,X \ X=1/2 cycle |
42412 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
42413 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
42415 \ ------------------------------\
42416 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
42417 \ ------------------------------\
42418 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42419 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
42420 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42421 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42422 SUB #1,W \ decrement count loop
42423 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
42424 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42425 0<> WHILE \ ----> out of loop ----+
42426 \ RC5_compute_7/4_Time_out: \ |
42427 ADD X,Y \ | out of bound = 7/4 period
42428 \ RC5_WaitHalfCycleP1.2_IFG: \ |
42430 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
42431 0>= IF \ | if cycle time out of bound
42432 BIC #$30,&TA0CTL \ | stop timer_A0
42433 RETI \ | then quit to do nothing
42435 \ ------------------------------\ |
42436 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
42438 MOV &TA0R,X \ | | get new RC5_period value
42439 REPEAT \ ----> loop back --+ |
42440 \ ------------------------------\ |
42441 \ RC5_SampleEndOf: \ <---------------------+
42442 \ ------------------------------\
42443 BIC #$30,&TA0CTL \ stop timer_A0
42444 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
42445 \ ******************************\
42446 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42447 \ ******************************\
42448 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
42449 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
42450 XOR IP,X \ (new XOR old) Toggle bit (13)
42451 BIT #BIT13,X \ X(13) = New_RC5_command
42452 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
42454 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
42455 \ ******************************\
42456 \ RC5_ComputeNewRC5word \
42457 \ ******************************\
42459 MOV &BASE,2(PSP) \ save variable BASE before use
42460 MOV TOS,0(PSP) \ save TOS before use
42461 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
42462 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
42463 \ ******************************\
42464 \ RC5_ComputeC6bit \
42465 \ ******************************\
42466 BIT #$4000,IP \ test /C6 bit in IP
42467 0= IF BIS #$40,TOS \ set C6 bit in S
42468 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
42469 \ ******************************\
42470 \ RC5_CommandByteIsDone \ RC5_code --
42471 \ ******************************\
42473 \ ------------------------------\
42474 \ Display IR_RC5 code \
42475 \ ------------------------------\
42476 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
42477 \ ------------------------------\
42478 LO2HI \ switch from assembler to FORTH
42479 ['] LCD_CLEAR IS CR \ redirects CR
42480 ['] LCD_WrC IS EMIT \ redirects EMIT
42481 $10 BASE ! \ change BASE to hexadecimal
42482 CR ." $" 2 U.R \ print IR_RC5 code
42483 ['] (CR) IS CR \ restore CR
42484 ['] (EMIT) IS EMIT \ restore EMIT
42485 HI2LO \ switch from FORTH to assembler
42486 \ ------------------------------\
42487 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
42488 \ ------------------------------\
42489 MOV @PSP+,&BASE \ restore variable BASE
42490 RETI \ CPU is ON, GIE is OFF
42495 \ ------------------------------\
42496 \ TB0CTL = %0000 0010 1001 0100\$3C0
42497 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42498 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42499 \ -- \ID input divider \ 10 = /4
42500 \ -- \MC Mode Control \ 01 = up to TB0CCR0
42501 \ - \TBCLR TimerB Clear
42504 \ --------------------------------\\
42505 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42506 \ -- \CM Capture Mode
42511 \ --- \OUTMOD \ 011 = set/reset
42517 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
42519 \ ------------------------------\
42520 \ set TimerB to make 50kHz PWM \
42521 \ ------------------------------\
42522 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42523 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
42524 \ ------------------------------\
42525 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42526 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
42527 \ ------------------------------\
42528 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42529 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
42530 \ ------------------------------\
42531 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42532 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
42533 \ ------------------------------\
42534 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42535 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
42536 \ ------------------------------\
42537 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
42538 \ ------------------------------\
42539 \ set TimerB to generate PWM for LCD_Vo
42540 \ ------------------------------\
42541 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
42542 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
42543 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42544 \ ------------------------------\
42545 BIS.B #LCDVo,&LCDVo_DIR \
42546 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
42547 \ ------------------------------\
42548 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42549 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42550 \ ------------------------------\
42551 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42552 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42553 \ ------------------------------\
42554 \ WDT interval init part \
42555 \ ------------------------------\
42556 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
42557 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
42558 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
42559 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
42560 \ ------------------------------\
42562 \ ------------------------------\
42563 BIS.B #RC5,&IR_IE \ enable RC5_Int
42564 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42565 \ ------------------------------\
42566 \ init interrupt vectors
42567 \ ------------------------------\
42568 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
42569 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42570 \ ------------------------------\
42571 \ define LPM mode for ACCEPT \
42572 \ ------------------------------\
42573 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42574 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42575 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42577 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
42579 \ ------------------------------\
42581 \ ------------------------------\
42582 $03E8 20_US \ 1- wait 20 ms
42583 $03 TOP_LCD \ 2- send DB5=DB4=1
42584 $CD 20_US \ 3- wait 4,1 ms
42585 $03 TOP_LCD \ 4- send again DB5=DB4=1
42586 $5 20_US \ 5- wait 0,1 ms
42587 $03 TOP_LCD \ 6- send again again DB5=DB4=1
42588 $2 20_US \ wait 40 us = LCD cycle
42589 $02 TOP_LCD \ 7- send DB5=1 DB4=0
42590 $2 20_US \ wait 40 us = LCD cycle
42591 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42592 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
42593 LCD_Clear \ 10- "LCD_Clear"
42594 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
42595 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
42596 LCD_Clear \ 10- "LCD_Clear"
42597 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
42598 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
42600 ['] (CR) IS CR \ ' (CR) is CR
42601 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
42603 ." RC5toLCD is running. Type STOP to quit"
42604 \ NOECHO \ uncomment to run this app without terminal connexion
42605 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
42606 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
42610 : STOP \ stops multitasking, must to be used before downloading app
42611 ['] (WARM) IS WARM \ remove START app from FORTH init process
42612 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
42620 CODE MAX \ n1 n2 -- n3 signed maximum
42621 CMP @PSP,TOS \ n2-n1
42622 S< ?GOTO FW1 \ n2<n1
42628 CODE MIN \ n1 n2 -- n3 signed minimum
42629 CMP @PSP,TOS \ n2-n1
42630 S< ?GOTO BW1 \ n2<n1
42636 : U.R \ u n -- display u unsigned in n width (n >= 2)
42638 R> OVER - 0 MAX SPACES TYPE
42642 CODE 20_US \ n -- n * 20 us
42643 BEGIN \ 3 cycles loop + 6~
42644 \ MOV #5,W \ 3 MCLK = 1 MHz
42645 \ MOV #23,W \ 3 MCLK = 4 MHz
42646 MOV #51,W \ 3 MCLK = 8 MHz
42647 \ MOV #104,W \ 3 MCLK = 16 MHz
42648 \ MOV #158,W \ 3 MCLK = 24 MHz
42649 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
42659 CODE TOP_LCD \ LCD Sample
42660 \ \ if write : %xxxxWWWW --
42661 \ \ if read : -- %0000RRRR
42662 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
42663 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
42664 0= IF \ write LCD bits pattern
42665 AND.B #LCD_DB,TOS \
42666 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
42667 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42670 THEN \ read LCD bits pattern
42673 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42674 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
42675 AND.B #LCD_DB,TOS \
42680 CODE LCD_W \ byte -- write byte to LCD
42682 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
42683 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
42684 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
42685 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
42686 COLON \ high level word starts here
42687 TOP_LCD 2 20_US \ write high nibble first
42692 CODE LCD_WrC \ char -- Write Char
42693 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42698 CODE LCD_WrF \ func -- Write Fonction
42699 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42705 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
42710 $02 LCD_WrF 100 20_us
42714 \ : LCD_Entry_set $04 OR LCD_WrF ;
42716 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
42718 \ : LCD_Display_Shift $10 OR LCD_WrF ;
42720 \ : LCD_Fn_Set $20 OR LCD_WrF ;
42722 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
42724 \ : LCD_Goto $80 OR LCD_WrF ;
42726 \ CODE LCD_R \ -- byte read byte from LCD
42727 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
42728 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
42729 \ COLON \ starts a FORTH word
42730 \ TOP_LCD 2 20_us \ -- %0000HHHH
42731 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
42732 \ HI2LO \ switch from FORTH to assembler
42733 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
42734 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
42735 \ MOV @RSP+,IP \ restore IP saved by COLON
42740 \ CODE LCD_RdS \ -- status Read Status
42741 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42746 \ CODE LCD_RdC \ -- char Read Char
42747 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42752 \ -------------+------+------+------+------++---+---+---+---+---------+
42753 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
42754 \ -------------+------+------+------+------++---+---+---+---+---------+
42755 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
42756 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
42757 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
42758 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
42759 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
42760 \ -------------+------+------+------+------++---+---+---+---+---------+
42763 \ ******************************\
42764 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
42765 \ ******************************\
42766 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
42767 \ ------------------------------\
42768 \ define LPM mode for ACCEPT \
42769 \ ------------------------------\
42770 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42771 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42772 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42773 BIT.B #SW2,&SW2_IN \ test switch S2
42774 0= IF \ case of switch S2 pressed
42775 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
42777 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
42780 BIT.B #SW1,&SW1_IN \ test switch S1 input
42781 0= IF \ case of Switch S1 pressed
42782 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
42784 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
42788 RETI \ CPU is ON, GIE is OFF
42793 \ ------------------------------\
42794 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
42795 \ ******************************\
42796 ASM RC5_INT \ wake up on Px.RC5 change interrupt
42797 \ ******************************\
42798 \ \ in : SR(9)=old Toggle bit memory (ADD on)
42799 \ \ SMclock = 8|16|24 MHz
42800 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
42801 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
42802 \ \ SR(9)=new Toggle bit memory (ADD on)
42803 \ ------------------------------\
42804 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
42805 \ ------------------------------\
42806 \ define LPM mode for ACCEPT \
42807 \ ------------------------------\
42808 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42809 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42810 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42811 \ ------------------------------\
42812 \ RC5_FirstStartBitHalfCycle: \
42813 \ ------------------------------\
42814 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
42815 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
42816 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
42817 MOV #1778,X \ RC5_Period in us
42818 MOV #14,W \ count of loop
42820 \ ------------------------------\
42821 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
42822 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
42823 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
42824 \ RC5_Compute_3/4_Period: \ |
42825 RRUM #1,X \ X=1/2 cycle |
42829 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
42830 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
42832 \ ------------------------------\
42833 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
42834 \ ------------------------------\
42835 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42836 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
42837 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42838 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42839 SUB #1,W \ decrement count loop
42840 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
42841 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42842 0<> WHILE \ ----> out of loop ----+
42843 \ RC5_compute_7/4_Time_out: \ |
42844 ADD X,Y \ | out of bound = 7/4 period
42845 \ RC5_WaitHalfCycleP1.2_IFG: \ |
42847 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
42848 0>= IF \ | if cycle time out of bound
42849 BIC #$30,&TA0CTL \ | stop timer_A0
42850 RETI \ | then quit to do nothing
42852 \ ------------------------------\ |
42853 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
42855 MOV &TA0R,X \ | | get new RC5_period value
42856 REPEAT \ ----> loop back --+ |
42857 \ ------------------------------\ |
42858 \ RC5_SampleEndOf: \ <---------------------+
42859 \ ------------------------------\
42860 BIC #$30,&TA0CTL \ stop timer_A0
42861 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
42862 \ ******************************\
42863 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42864 \ ******************************\
42865 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
42866 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
42867 XOR IP,X \ (new XOR old) Toggle bit (13)
42868 BIT #BIT13,X \ X(13) = New_RC5_command
42869 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
42871 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
42872 \ ******************************\
42873 \ RC5_ComputeNewRC5word \
42874 \ ******************************\
42876 MOV &BASE,2(PSP) \ save variable BASE before use
42877 MOV TOS,0(PSP) \ save TOS before use
42878 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
42879 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
42880 \ ******************************\
42881 \ RC5_ComputeC6bit \
42882 \ ******************************\
42883 BIT #$4000,IP \ test /C6 bit in IP
42884 0= IF BIS #$40,TOS \ set C6 bit in S
42885 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
42886 \ ******************************\
42887 \ RC5_CommandByteIsDone \ RC5_code --
42888 \ ******************************\
42890 \ ------------------------------\
42891 \ Display IR_RC5 code \
42892 \ ------------------------------\
42893 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
42894 \ ------------------------------\
42895 LO2HI \ switch from assembler to FORTH
42896 ['] LCD_CLEAR IS CR \ redirects CR
42897 ['] LCD_WrC IS EMIT \ redirects EMIT
42898 $10 BASE ! \ change BASE to hexadecimal
42899 CR ." $" 2 U.R \ print IR_RC5 code
42900 ['] (CR) IS CR \ restore CR
42901 ['] (EMIT) IS EMIT \ restore EMIT
42902 HI2LO \ switch from FORTH to assembler
42903 \ ------------------------------\
42904 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
42905 \ ------------------------------\
42906 MOV @PSP+,&BASE \ restore variable BASE
42907 RETI \ CPU is ON, GIE is OFF
42912 \ ------------------------------\
42913 \ TB0CTL = %0000 0010 1001 0100\$3C0
42914 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42915 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42916 \ -- \ID input divider \ 10 = /4
42917 \ -- \MC Mode Control \ 01 = up to TB0CCR0
42918 \ - \TBCLR TimerB Clear
42921 \ --------------------------------\\
42922 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42923 \ -- \CM Capture Mode
42928 \ --- \OUTMOD \ 011 = set/reset
42934 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
42936 \ ------------------------------\
42937 \ set TimerB to make 50kHz PWM \
42938 \ ------------------------------\
42939 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42940 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
42941 \ ------------------------------\
42942 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
42943 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
42944 \ ------------------------------\
42945 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42946 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
42947 \ ------------------------------\
42948 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42949 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
42950 \ ------------------------------\
42951 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
42952 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
42953 \ ------------------------------\
42954 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
42955 \ ------------------------------\
42956 \ set TimerB to generate PWM for LCD_Vo
42957 \ ------------------------------\
42958 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
42959 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
42960 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42961 \ ------------------------------\
42962 BIS.B #LCDVo,&LCDVo_DIR \
42963 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
42964 \ ------------------------------\
42965 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42966 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42967 \ ------------------------------\
42968 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42969 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42970 \ ------------------------------\
42971 \ WDT interval init part \
42972 \ ------------------------------\
42973 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
42974 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
42975 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
42976 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
42977 \ ------------------------------\
42979 \ ------------------------------\
42980 BIS.B #RC5,&IR_IE \ enable RC5_Int
42981 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42982 \ ------------------------------\
42983 \ init interrupt vectors
42984 \ ------------------------------\
42985 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
42986 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42987 \ ------------------------------\
42988 \ define LPM mode for ACCEPT \
42989 \ ------------------------------\
42990 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42991 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42992 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42994 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
42996 \ ------------------------------\
42998 \ ------------------------------\
42999 $03E8 20_US \ 1- wait 20 ms
43000 $03 TOP_LCD \ 2- send DB5=DB4=1
43001 $CD 20_US \ 3- wait 4,1 ms
43002 $03 TOP_LCD \ 4- send again DB5=DB4=1
43003 $5 20_US \ 5- wait 0,1 ms
43004 $03 TOP_LCD \ 6- send again again DB5=DB4=1
43005 $2 20_US \ wait 40 us = LCD cycle
43006 $02 TOP_LCD \ 7- send DB5=1 DB4=0
43007 $2 20_US \ wait 40 us = LCD cycle
43008 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43009 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43010 LCD_Clear \ 10- "LCD_Clear"
43011 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43012 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43013 LCD_Clear \ 10- "LCD_Clear"
43014 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43015 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43017 ['] (CR) IS CR \ ' (CR) is CR
43018 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
43020 ." RC5toLCD is running. Type STOP to quit"
43021 \ NOECHO \ uncomment to run this app without terminal connexion
43022 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
43023 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
43027 : STOP \ stops multitasking, must to be used before downloading app
43028 ['] (WARM) IS WARM \ remove START app from FORTH init process
43029 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
43037 CODE MAX \ n1 n2 -- n3 signed maximum
43038 CMP @PSP,TOS \ n2-n1
43039 S< ?GOTO FW1 \ n2<n1
43045 CODE MIN \ n1 n2 -- n3 signed minimum
43046 CMP @PSP,TOS \ n2-n1
43047 S< ?GOTO BW1 \ n2<n1
43053 : U.R \ u n -- display u unsigned in n width (n >= 2)
43055 R> OVER - 0 MAX SPACES TYPE
43059 CODE 20_US \ n -- n * 20 us
43060 BEGIN \ 3 cycles loop + 6~
43061 \ MOV #5,W \ 3 MCLK = 1 MHz
43062 \ MOV #23,W \ 3 MCLK = 4 MHz
43063 MOV #51,W \ 3 MCLK = 8 MHz
43064 \ MOV #104,W \ 3 MCLK = 16 MHz
43065 \ MOV #158,W \ 3 MCLK = 24 MHz
43066 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
43076 CODE TOP_LCD \ LCD Sample
43077 \ \ if write : %xxxxWWWW --
43078 \ \ if read : -- %0000RRRR
43079 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43080 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43081 0= IF \ write LCD bits pattern
43082 AND.B #LCD_DB,TOS \
43083 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43084 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43087 THEN \ read LCD bits pattern
43090 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43091 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43092 AND.B #LCD_DB,TOS \
43097 CODE LCD_W \ byte -- write byte to LCD
43099 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
43100 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
43101 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43102 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43103 COLON \ high level word starts here
43104 TOP_LCD 2 20_US \ write high nibble first
43109 CODE LCD_WrC \ char -- Write Char
43110 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43115 CODE LCD_WrF \ func -- Write Fonction
43116 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43122 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
43127 $02 LCD_WrF 100 20_us
43131 \ : LCD_Entry_set $04 OR LCD_WrF ;
43133 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
43135 \ : LCD_Display_Shift $10 OR LCD_WrF ;
43137 \ : LCD_Fn_Set $20 OR LCD_WrF ;
43139 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
43141 \ : LCD_Goto $80 OR LCD_WrF ;
43143 \ CODE LCD_R \ -- byte read byte from LCD
43144 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43145 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43146 \ COLON \ starts a FORTH word
43147 \ TOP_LCD 2 20_us \ -- %0000HHHH
43148 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
43149 \ HI2LO \ switch from FORTH to assembler
43150 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
43151 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
43152 \ MOV @RSP+,IP \ restore IP saved by COLON
43157 \ CODE LCD_RdS \ -- status Read Status
43158 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43163 \ CODE LCD_RdC \ -- char Read Char
43164 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43169 \ -------------+------+------+------+------++---+---+---+---+---------+
43170 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
43171 \ -------------+------+------+------+------++---+---+---+---+---------+
43172 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
43173 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
43174 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
43175 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
43176 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
43177 \ -------------+------+------+------+------++---+---+---+---+---------+
43180 \ ******************************\
43181 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
43182 \ ******************************\
43183 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
43184 \ ------------------------------\
43185 \ define LPM mode for ACCEPT \
43186 \ ------------------------------\
43187 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43188 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43189 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43190 BIT.B #SW2,&SW2_IN \ test switch S2
43191 0= IF \ case of switch S2 pressed
43192 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
43194 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
43197 BIT.B #SW1,&SW1_IN \ test switch S1 input
43198 0= IF \ case of Switch S1 pressed
43199 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
43201 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
43205 RETI \ CPU is ON, GIE is OFF
43210 \ ------------------------------\
43211 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
43212 \ ******************************\
43213 ASM RC5_INT \ wake up on Px.RC5 change interrupt
43214 \ ******************************\
43215 \ \ in : SR(9)=old Toggle bit memory (ADD on)
43216 \ \ SMclock = 8|16|24 MHz
43217 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
43218 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
43219 \ \ SR(9)=new Toggle bit memory (ADD on)
43220 \ ------------------------------\
43221 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
43222 \ ------------------------------\
43223 \ define LPM mode for ACCEPT \
43224 \ ------------------------------\
43225 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43226 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43227 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43228 \ ------------------------------\
43229 \ RC5_FirstStartBitHalfCycle: \
43230 \ ------------------------------\
43231 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
43232 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
43233 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
43234 MOV #1778,X \ RC5_Period in us
43235 MOV #14,W \ count of loop
43237 \ ------------------------------\
43238 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
43239 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
43240 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
43241 \ RC5_Compute_3/4_Period: \ |
43242 RRUM #1,X \ X=1/2 cycle |
43246 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
43247 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
43249 \ ------------------------------\
43250 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
43251 \ ------------------------------\
43252 BIT.B #RC5,&IR_IN \ C_flag = IR bit
43253 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
43254 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
43255 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
43256 SUB #1,W \ decrement count loop
43257 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
43258 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
43259 0<> WHILE \ ----> out of loop ----+
43260 \ RC5_compute_7/4_Time_out: \ |
43261 ADD X,Y \ | out of bound = 7/4 period
43262 \ RC5_WaitHalfCycleP1.2_IFG: \ |
43264 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
43265 0>= IF \ | if cycle time out of bound
43266 BIC #$30,&TA0CTL \ | stop timer_A0
43267 RETI \ | then quit to do nothing
43269 \ ------------------------------\ |
43270 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
43272 MOV &TA0R,X \ | | get new RC5_period value
43273 REPEAT \ ----> loop back --+ |
43274 \ ------------------------------\ |
43275 \ RC5_SampleEndOf: \ <---------------------+
43276 \ ------------------------------\
43277 BIC #$30,&TA0CTL \ stop timer_A0
43278 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
43279 \ ******************************\
43280 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
43281 \ ******************************\
43282 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
43283 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
43284 XOR IP,X \ (new XOR old) Toggle bit (13)
43285 BIT #BIT13,X \ X(13) = New_RC5_command
43286 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
43288 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
43289 \ ******************************\
43290 \ RC5_ComputeNewRC5word \
43291 \ ******************************\
43293 MOV &BASE,2(PSP) \ save variable BASE before use
43294 MOV TOS,0(PSP) \ save TOS before use
43295 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
43296 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
43297 \ ******************************\
43298 \ RC5_ComputeC6bit \
43299 \ ******************************\
43300 BIT #$4000,IP \ test /C6 bit in IP
43301 0= IF BIS #$40,TOS \ set C6 bit in S
43302 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
43303 \ ******************************\
43304 \ RC5_CommandByteIsDone \ RC5_code --
43305 \ ******************************\
43307 \ ------------------------------\
43308 \ Display IR_RC5 code \
43309 \ ------------------------------\
43310 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
43311 \ ------------------------------\
43312 LO2HI \ switch from assembler to FORTH
43313 ['] LCD_CLEAR IS CR \ redirects CR
43314 ['] LCD_WrC IS EMIT \ redirects EMIT
43315 $10 BASE ! \ change BASE to hexadecimal
43316 CR ." $" 2 U.R \ print IR_RC5 code
43317 ['] (CR) IS CR \ restore CR
43318 ['] (EMIT) IS EMIT \ restore EMIT
43319 HI2LO \ switch from FORTH to assembler
43320 \ ------------------------------\
43321 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
43322 \ ------------------------------\
43323 MOV @PSP+,&BASE \ restore variable BASE
43324 RETI \ CPU is ON, GIE is OFF
43329 \ ------------------------------\
43330 \ TB0CTL = %0000 0010 1001 0100\$3C0
43331 \ - - \CNTL Counter lentgh \ 00 = 16 bits
43332 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
43333 \ -- \ID input divider \ 10 = /4
43334 \ -- \MC Mode Control \ 01 = up to TB0CCR0
43335 \ - \TBCLR TimerB Clear
43338 \ --------------------------------\\
43339 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43340 \ -- \CM Capture Mode
43345 \ --- \OUTMOD \ 011 = set/reset
43351 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
43353 \ ------------------------------\
43354 \ set TimerB to make 50kHz PWM \
43355 \ ------------------------------\
43356 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43357 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
43358 \ ------------------------------\
43359 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43360 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
43361 \ ------------------------------\
43362 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43363 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
43364 \ ------------------------------\
43365 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43366 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
43367 \ ------------------------------\
43368 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43369 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
43370 \ ------------------------------\
43371 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
43372 \ ------------------------------\
43373 \ set TimerB to generate PWM for LCD_Vo
43374 \ ------------------------------\
43375 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
43376 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
43377 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43378 \ ------------------------------\
43379 BIS.B #LCDVo,&LCDVo_DIR \
43380 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
43381 \ ------------------------------\
43382 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43383 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43384 \ ------------------------------\
43385 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
43386 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
43387 \ ------------------------------\
43388 \ WDT interval init part \
43389 \ ------------------------------\
43390 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
43391 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
43392 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
43393 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
43394 \ ------------------------------\
43396 \ ------------------------------\
43397 BIS.B #RC5,&IR_IE \ enable RC5_Int
43398 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
43399 \ ------------------------------\
43400 \ init interrupt vectors
43401 \ ------------------------------\
43402 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
43403 MOV #RC5_INT,&IR_Vec \ init interrupt vector
43404 \ ------------------------------\
43405 \ define LPM mode for ACCEPT \
43406 \ ------------------------------\
43407 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43408 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43409 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43411 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
43413 \ ------------------------------\
43415 \ ------------------------------\
43416 $03E8 20_US \ 1- wait 20 ms
43417 $03 TOP_LCD \ 2- send DB5=DB4=1
43418 $CD 20_US \ 3- wait 4,1 ms
43419 $03 TOP_LCD \ 4- send again DB5=DB4=1
43420 $5 20_US \ 5- wait 0,1 ms
43421 $03 TOP_LCD \ 6- send again again DB5=DB4=1
43422 $2 20_US \ wait 40 us = LCD cycle
43423 $02 TOP_LCD \ 7- send DB5=1 DB4=0
43424 $2 20_US \ wait 40 us = LCD cycle
43425 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43426 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43427 LCD_Clear \ 10- "LCD_Clear"
43428 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43429 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43430 LCD_Clear \ 10- "LCD_Clear"
43431 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43432 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43434 ['] (CR) IS CR \ ' (CR) is CR
43435 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
43437 ." RC5toLCD is running. Type STOP to quit"
43438 \ NOECHO \ uncomment to run this app without terminal connexion
43439 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
43440 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
43444 : STOP \ stops multitasking, must to be used before downloading app
43445 ['] (WARM) IS WARM \ remove START app from FORTH init process
43446 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
43454 CODE MAX \ n1 n2 -- n3 signed maximum
43455 CMP @PSP,TOS \ n2-n1
43456 S< ?GOTO FW1 \ n2<n1
43462 CODE MIN \ n1 n2 -- n3 signed minimum
43463 CMP @PSP,TOS \ n2-n1
43464 S< ?GOTO BW1 \ n2<n1
43470 : U.R \ u n -- display u unsigned in n width (n >= 2)
43472 R> OVER - 0 MAX SPACES TYPE
43476 CODE 20_US \ n -- n * 20 us
43477 BEGIN \ 3 cycles loop + 6~
43478 \ MOV #5,W \ 3 MCLK = 1 MHz
43479 \ MOV #23,W \ 3 MCLK = 4 MHz
43480 MOV #51,W \ 3 MCLK = 8 MHz
43481 \ MOV #104,W \ 3 MCLK = 16 MHz
43482 \ MOV #158,W \ 3 MCLK = 24 MHz
43483 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
43493 CODE TOP_LCD \ LCD Sample
43494 \ \ if write : %xxxxWWWW --
43495 \ \ if read : -- %0000RRRR
43496 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43497 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43498 0= IF \ write LCD bits pattern
43499 AND.B #LCD_DB,TOS \
43500 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43501 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43504 THEN \ read LCD bits pattern
43507 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43508 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43509 AND.B #LCD_DB,TOS \
43514 CODE LCD_W \ byte -- write byte to LCD
43516 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
43517 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
43518 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43519 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43520 COLON \ high level word starts here
43521 TOP_LCD 2 20_US \ write high nibble first
43526 CODE LCD_WrC \ char -- Write Char
43527 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43532 CODE LCD_WrF \ func -- Write Fonction
43533 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43539 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
43544 $02 LCD_WrF 100 20_us
43548 \ : LCD_Entry_set $04 OR LCD_WrF ;
43550 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
43552 \ : LCD_Display_Shift $10 OR LCD_WrF ;
43554 \ : LCD_Fn_Set $20 OR LCD_WrF ;
43556 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
43558 \ : LCD_Goto $80 OR LCD_WrF ;
43560 \ CODE LCD_R \ -- byte read byte from LCD
43561 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43562 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43563 \ COLON \ starts a FORTH word
43564 \ TOP_LCD 2 20_us \ -- %0000HHHH
43565 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
43566 \ HI2LO \ switch from FORTH to assembler
43567 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
43568 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
43569 \ MOV @RSP+,IP \ restore IP saved by COLON
43574 \ CODE LCD_RdS \ -- status Read Status
43575 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43580 \ CODE LCD_RdC \ -- char Read Char
43581 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43586 \ -------------+------+------+------+------++---+---+---+---+---------+
43587 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
43588 \ -------------+------+------+------+------++---+---+---+---+---------+
43589 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
43590 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
43591 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
43592 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
43593 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
43594 \ -------------+------+------+------+------++---+---+---+---+---------+
43597 \ ******************************\
43598 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
43599 \ ******************************\
43600 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
43601 \ ------------------------------\
43602 \ define LPM mode for ACCEPT \
43603 \ ------------------------------\
43604 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43605 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43606 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43607 BIT.B #SW2,&SW2_IN \ test switch S2
43608 0= IF \ case of switch S2 pressed
43609 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
43611 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
43614 BIT.B #SW1,&SW1_IN \ test switch S1 input
43615 0= IF \ case of Switch S1 pressed
43616 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
43618 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
43622 RETI \ CPU is ON, GIE is OFF
43627 \ ------------------------------\
43628 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
43629 \ ******************************\
43630 ASM RC5_INT \ wake up on Px.RC5 change interrupt
43631 \ ******************************\
43632 \ \ in : SR(9)=old Toggle bit memory (ADD on)
43633 \ \ SMclock = 8|16|24 MHz
43634 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
43635 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
43636 \ \ SR(9)=new Toggle bit memory (ADD on)
43637 \ ------------------------------\
43638 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
43639 \ ------------------------------\
43640 \ define LPM mode for ACCEPT \
43641 \ ------------------------------\
43642 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43643 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43644 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43645 \ ------------------------------\
43646 \ RC5_FirstStartBitHalfCycle: \
43647 \ ------------------------------\
43648 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
43649 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
43650 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
43651 MOV #1778,X \ RC5_Period in us
43652 MOV #14,W \ count of loop
43654 \ ------------------------------\
43655 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
43656 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
43657 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
43658 \ RC5_Compute_3/4_Period: \ |
43659 RRUM #1,X \ X=1/2 cycle |
43663 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
43664 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
43666 \ ------------------------------\
43667 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
43668 \ ------------------------------\
43669 BIT.B #RC5,&IR_IN \ C_flag = IR bit
43670 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
43671 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
43672 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
43673 SUB #1,W \ decrement count loop
43674 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
43675 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
43676 0<> WHILE \ ----> out of loop ----+
43677 \ RC5_compute_7/4_Time_out: \ |
43678 ADD X,Y \ | out of bound = 7/4 period
43679 \ RC5_WaitHalfCycleP1.2_IFG: \ |
43681 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
43682 0>= IF \ | if cycle time out of bound
43683 BIC #$30,&TA0CTL \ | stop timer_A0
43684 RETI \ | then quit to do nothing
43686 \ ------------------------------\ |
43687 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
43689 MOV &TA0R,X \ | | get new RC5_period value
43690 REPEAT \ ----> loop back --+ |
43691 \ ------------------------------\ |
43692 \ RC5_SampleEndOf: \ <---------------------+
43693 \ ------------------------------\
43694 BIC #$30,&TA0CTL \ stop timer_A0
43695 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
43696 \ ******************************\
43697 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
43698 \ ******************************\
43699 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
43700 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
43701 XOR IP,X \ (new XOR old) Toggle bit (13)
43702 BIT #BIT13,X \ X(13) = New_RC5_command
43703 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
43705 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
43706 \ ******************************\
43707 \ RC5_ComputeNewRC5word \
43708 \ ******************************\
43710 MOV &BASE,2(PSP) \ save variable BASE before use
43711 MOV TOS,0(PSP) \ save TOS before use
43712 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
43713 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
43714 \ ******************************\
43715 \ RC5_ComputeC6bit \
43716 \ ******************************\
43717 BIT #$4000,IP \ test /C6 bit in IP
43718 0= IF BIS #$40,TOS \ set C6 bit in S
43719 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
43720 \ ******************************\
43721 \ RC5_CommandByteIsDone \ RC5_code --
43722 \ ******************************\
43724 \ ------------------------------\
43725 \ Display IR_RC5 code \
43726 \ ------------------------------\
43727 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
43728 \ ------------------------------\
43729 LO2HI \ switch from assembler to FORTH
43730 ['] LCD_CLEAR IS CR \ redirects CR
43731 ['] LCD_WrC IS EMIT \ redirects EMIT
43732 $10 BASE ! \ change BASE to hexadecimal
43733 CR ." $" 2 U.R \ print IR_RC5 code
43734 ['] (CR) IS CR \ restore CR
43735 ['] (EMIT) IS EMIT \ restore EMIT
43736 HI2LO \ switch from FORTH to assembler
43737 \ ------------------------------\
43738 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
43739 \ ------------------------------\
43740 MOV @PSP+,&BASE \ restore variable BASE
43741 RETI \ CPU is ON, GIE is OFF
43746 \ ------------------------------\
43747 \ TB0CTL = %0000 0010 1001 0100\$3C0
43748 \ - - \CNTL Counter lentgh \ 00 = 16 bits
43749 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
43750 \ -- \ID input divider \ 10 = /4
43751 \ -- \MC Mode Control \ 01 = up to TB0CCR0
43752 \ - \TBCLR TimerB Clear
43755 \ --------------------------------\\
43756 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43757 \ -- \CM Capture Mode
43762 \ --- \OUTMOD \ 011 = set/reset
43768 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
43770 \ ------------------------------\
43771 \ set TimerB to make 50kHz PWM \
43772 \ ------------------------------\
43773 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43774 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
43775 \ ------------------------------\
43776 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
43777 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
43778 \ ------------------------------\
43779 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43780 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
43781 \ ------------------------------\
43782 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43783 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
43784 \ ------------------------------\
43785 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
43786 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
43787 \ ------------------------------\
43788 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
43789 \ ------------------------------\
43790 \ set TimerB to generate PWM for LCD_Vo
43791 \ ------------------------------\
43792 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
43793 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
43794 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43795 \ ------------------------------\
43796 BIS.B #LCDVo,&LCDVo_DIR \
43797 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
43798 \ ------------------------------\
43799 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43800 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43801 \ ------------------------------\
43802 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
43803 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
43804 \ ------------------------------\
43805 \ WDT interval init part \
43806 \ ------------------------------\
43807 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
43808 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
43809 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
43810 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
43811 \ ------------------------------\
43813 \ ------------------------------\
43814 BIS.B #RC5,&IR_IE \ enable RC5_Int
43815 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
43816 \ ------------------------------\
43817 \ init interrupt vectors
43818 \ ------------------------------\
43819 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
43820 MOV #RC5_INT,&IR_Vec \ init interrupt vector
43821 \ ------------------------------\
43822 \ define LPM mode for ACCEPT \
43823 \ ------------------------------\
43824 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43825 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43826 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43828 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
43830 \ ------------------------------\
43832 \ ------------------------------\
43833 $03E8 20_US \ 1- wait 20 ms
43834 $03 TOP_LCD \ 2- send DB5=DB4=1
43835 $CD 20_US \ 3- wait 4,1 ms
43836 $03 TOP_LCD \ 4- send again DB5=DB4=1
43837 $5 20_US \ 5- wait 0,1 ms
43838 $03 TOP_LCD \ 6- send again again DB5=DB4=1
43839 $2 20_US \ wait 40 us = LCD cycle
43840 $02 TOP_LCD \ 7- send DB5=1 DB4=0
43841 $2 20_US \ wait 40 us = LCD cycle
43842 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43843 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43844 LCD_Clear \ 10- "LCD_Clear"
43845 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43846 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43847 LCD_Clear \ 10- "LCD_Clear"
43848 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43849 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43851 ['] (CR) IS CR \ ' (CR) is CR
43852 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
43854 ." RC5toLCD is running. Type STOP to quit"
43855 \ NOECHO \ uncomment to run this app without terminal connexion
43856 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
43857 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
43861 : STOP \ stops multitasking, must to be used before downloading app
43862 ['] (WARM) IS WARM \ remove START app from FORTH init process
43863 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
43871 CODE MAX \ n1 n2 -- n3 signed maximum
43872 CMP @PSP,TOS \ n2-n1
43873 S< ?GOTO FW1 \ n2<n1
43879 CODE MIN \ n1 n2 -- n3 signed minimum
43880 CMP @PSP,TOS \ n2-n1
43881 S< ?GOTO BW1 \ n2<n1
43887 : U.R \ u n -- display u unsigned in n width (n >= 2)
43889 R> OVER - 0 MAX SPACES TYPE
43893 CODE 20_US \ n -- n * 20 us
43894 BEGIN \ 3 cycles loop + 6~
43895 \ MOV #5,W \ 3 MCLK = 1 MHz
43896 \ MOV #23,W \ 3 MCLK = 4 MHz
43897 MOV #51,W \ 3 MCLK = 8 MHz
43898 \ MOV #104,W \ 3 MCLK = 16 MHz
43899 \ MOV #158,W \ 3 MCLK = 24 MHz
43900 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
43910 CODE TOP_LCD \ LCD Sample
43911 \ \ if write : %xxxxWWWW --
43912 \ \ if read : -- %0000RRRR
43913 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43914 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43915 0= IF \ write LCD bits pattern
43916 AND.B #LCD_DB,TOS \
43917 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43918 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43921 THEN \ read LCD bits pattern
43924 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43925 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43926 AND.B #LCD_DB,TOS \
43931 CODE LCD_W \ byte -- write byte to LCD
43933 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
43934 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
43935 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43936 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43937 COLON \ high level word starts here
43938 TOP_LCD 2 20_US \ write high nibble first
43943 CODE LCD_WrC \ char -- Write Char
43944 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43949 CODE LCD_WrF \ func -- Write Fonction
43950 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43956 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
43961 $02 LCD_WrF 100 20_us
43965 \ : LCD_Entry_set $04 OR LCD_WrF ;
43967 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
43969 \ : LCD_Display_Shift $10 OR LCD_WrF ;
43971 \ : LCD_Fn_Set $20 OR LCD_WrF ;
43973 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
43975 \ : LCD_Goto $80 OR LCD_WrF ;
43977 \ CODE LCD_R \ -- byte read byte from LCD
43978 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43979 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43980 \ COLON \ starts a FORTH word
43981 \ TOP_LCD 2 20_us \ -- %0000HHHH
43982 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
43983 \ HI2LO \ switch from FORTH to assembler
43984 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
43985 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
43986 \ MOV @RSP+,IP \ restore IP saved by COLON
43991 \ CODE LCD_RdS \ -- status Read Status
43992 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43997 \ CODE LCD_RdC \ -- char Read Char
43998 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44003 \ -------------+------+------+------+------++---+---+---+---+---------+
44004 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
44005 \ -------------+------+------+------+------++---+---+---+---+---------+
44006 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
44007 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
44008 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
44009 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
44010 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
44011 \ -------------+------+------+------+------++---+---+---+---+---------+
44014 \ ******************************\
44015 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44016 \ ******************************\
44017 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
44018 \ ------------------------------\
44019 \ define LPM mode for ACCEPT \
44020 \ ------------------------------\
44021 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44022 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44023 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44024 BIT.B #SW2,&SW2_IN \ test switch S2
44025 0= IF \ case of switch S2 pressed
44026 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
44028 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
44031 BIT.B #SW1,&SW1_IN \ test switch S1 input
44032 0= IF \ case of Switch S1 pressed
44033 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
44035 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
44039 RETI \ CPU is ON, GIE is OFF
44044 \ ------------------------------\
44045 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44046 \ ******************************\
44047 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44048 \ ******************************\
44049 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44050 \ \ SMclock = 8|16|24 MHz
44051 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
44052 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
44053 \ \ SR(9)=new Toggle bit memory (ADD on)
44054 \ ------------------------------\
44055 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
44056 \ ------------------------------\
44057 \ define LPM mode for ACCEPT \
44058 \ ------------------------------\
44059 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44060 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44061 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44062 \ ------------------------------\
44063 \ RC5_FirstStartBitHalfCycle: \
44064 \ ------------------------------\
44065 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
44066 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
44067 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
44068 MOV #1778,X \ RC5_Period in us
44069 MOV #14,W \ count of loop
44071 \ ------------------------------\
44072 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
44073 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
44074 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
44075 \ RC5_Compute_3/4_Period: \ |
44076 RRUM #1,X \ X=1/2 cycle |
44080 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
44081 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
44083 \ ------------------------------\
44084 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
44085 \ ------------------------------\
44086 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44087 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
44088 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44089 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44090 SUB #1,W \ decrement count loop
44091 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
44092 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44093 0<> WHILE \ ----> out of loop ----+
44094 \ RC5_compute_7/4_Time_out: \ |
44095 ADD X,Y \ | out of bound = 7/4 period
44096 \ RC5_WaitHalfCycleP1.2_IFG: \ |
44098 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
44099 0>= IF \ | if cycle time out of bound
44100 BIC #$30,&TA0CTL \ | stop timer_A0
44101 RETI \ | then quit to do nothing
44103 \ ------------------------------\ |
44104 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
44106 MOV &TA0R,X \ | | get new RC5_period value
44107 REPEAT \ ----> loop back --+ |
44108 \ ------------------------------\ |
44109 \ RC5_SampleEndOf: \ <---------------------+
44110 \ ------------------------------\
44111 BIC #$30,&TA0CTL \ stop timer_A0
44112 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
44113 \ ******************************\
44114 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44115 \ ******************************\
44116 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
44117 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
44118 XOR IP,X \ (new XOR old) Toggle bit (13)
44119 BIT #BIT13,X \ X(13) = New_RC5_command
44120 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
44122 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
44123 \ ******************************\
44124 \ RC5_ComputeNewRC5word \
44125 \ ******************************\
44127 MOV &BASE,2(PSP) \ save variable BASE before use
44128 MOV TOS,0(PSP) \ save TOS before use
44129 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
44130 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
44131 \ ******************************\
44132 \ RC5_ComputeC6bit \
44133 \ ******************************\
44134 BIT #$4000,IP \ test /C6 bit in IP
44135 0= IF BIS #$40,TOS \ set C6 bit in S
44136 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
44137 \ ******************************\
44138 \ RC5_CommandByteIsDone \ RC5_code --
44139 \ ******************************\
44141 \ ------------------------------\
44142 \ Display IR_RC5 code \
44143 \ ------------------------------\
44144 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
44145 \ ------------------------------\
44146 LO2HI \ switch from assembler to FORTH
44147 ['] LCD_CLEAR IS CR \ redirects CR
44148 ['] LCD_WrC IS EMIT \ redirects EMIT
44149 $10 BASE ! \ change BASE to hexadecimal
44150 CR ." $" 2 U.R \ print IR_RC5 code
44151 ['] (CR) IS CR \ restore CR
44152 ['] (EMIT) IS EMIT \ restore EMIT
44153 HI2LO \ switch from FORTH to assembler
44154 \ ------------------------------\
44155 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
44156 \ ------------------------------\
44157 MOV @PSP+,&BASE \ restore variable BASE
44158 RETI \ CPU is ON, GIE is OFF
44163 \ ------------------------------\
44164 \ TB0CTL = %0000 0010 1001 0100\$3C0
44165 \ - - \CNTL Counter lentgh \ 00 = 16 bits
44166 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
44167 \ -- \ID input divider \ 10 = /4
44168 \ -- \MC Mode Control \ 01 = up to TB0CCR0
44169 \ - \TBCLR TimerB Clear
44172 \ --------------------------------\\
44173 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44174 \ -- \CM Capture Mode
44179 \ --- \OUTMOD \ 011 = set/reset
44185 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
44187 \ ------------------------------\
44188 \ set TimerB to make 50kHz PWM \
44189 \ ------------------------------\
44190 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44191 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
44192 \ ------------------------------\
44193 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44194 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
44195 \ ------------------------------\
44196 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44197 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
44198 \ ------------------------------\
44199 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44200 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
44201 \ ------------------------------\
44202 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44203 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
44204 \ ------------------------------\
44205 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
44206 \ ------------------------------\
44207 \ set TimerB to generate PWM for LCD_Vo
44208 \ ------------------------------\
44209 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
44210 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
44211 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
44212 \ ------------------------------\
44213 BIS.B #LCDVo,&LCDVo_DIR \
44214 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
44215 \ ------------------------------\
44216 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
44217 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
44218 \ ------------------------------\
44219 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
44220 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
44221 \ ------------------------------\
44222 \ WDT interval init part \
44223 \ ------------------------------\
44224 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
44225 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
44226 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
44227 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
44228 \ ------------------------------\
44230 \ ------------------------------\
44231 BIS.B #RC5,&IR_IE \ enable RC5_Int
44232 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
44233 \ ------------------------------\
44234 \ init interrupt vectors
44235 \ ------------------------------\
44236 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
44237 MOV #RC5_INT,&IR_Vec \ init interrupt vector
44238 \ ------------------------------\
44239 \ define LPM mode for ACCEPT \
44240 \ ------------------------------\
44241 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44242 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44243 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44245 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
44247 \ ------------------------------\
44249 \ ------------------------------\
44250 $03E8 20_US \ 1- wait 20 ms
44251 $03 TOP_LCD \ 2- send DB5=DB4=1
44252 $CD 20_US \ 3- wait 4,1 ms
44253 $03 TOP_LCD \ 4- send again DB5=DB4=1
44254 $5 20_US \ 5- wait 0,1 ms
44255 $03 TOP_LCD \ 6- send again again DB5=DB4=1
44256 $2 20_US \ wait 40 us = LCD cycle
44257 $02 TOP_LCD \ 7- send DB5=1 DB4=0
44258 $2 20_US \ wait 40 us = LCD cycle
44259 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
44260 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
44261 LCD_Clear \ 10- "LCD_Clear"
44262 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
44263 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
44264 LCD_Clear \ 10- "LCD_Clear"
44265 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
44266 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
44268 ['] (CR) IS CR \ ' (CR) is CR
44269 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
44271 ." RC5toLCD is running. Type STOP to quit"
44272 \ NOECHO \ uncomment to run this app without terminal connexion
44273 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
44274 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
44278 : STOP \ stops multitasking, must to be used before downloading app
44279 ['] (WARM) IS WARM \ remove START app from FORTH init process
44280 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
44288 CODE MAX \ n1 n2 -- n3 signed maximum
44289 CMP @PSP,TOS \ n2-n1
44290 S< ?GOTO FW1 \ n2<n1
44296 CODE MIN \ n1 n2 -- n3 signed minimum
44297 CMP @PSP,TOS \ n2-n1
44298 S< ?GOTO BW1 \ n2<n1
44304 : U.R \ u n -- display u unsigned in n width (n >= 2)
44306 R> OVER - 0 MAX SPACES TYPE
44310 CODE 20_US \ n -- n * 20 us
44311 BEGIN \ 3 cycles loop + 6~
44312 \ MOV #5,W \ 3 MCLK = 1 MHz
44313 \ MOV #23,W \ 3 MCLK = 4 MHz
44314 MOV #51,W \ 3 MCLK = 8 MHz
44315 \ MOV #104,W \ 3 MCLK = 16 MHz
44316 \ MOV #158,W \ 3 MCLK = 24 MHz
44317 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
44327 CODE TOP_LCD \ LCD Sample
44328 \ \ if write : %xxxxWWWW --
44329 \ \ if read : -- %0000RRRR
44330 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
44331 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
44332 0= IF \ write LCD bits pattern
44333 AND.B #LCD_DB,TOS \
44334 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
44335 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44338 THEN \ read LCD bits pattern
44341 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44342 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
44343 AND.B #LCD_DB,TOS \
44348 CODE LCD_W \ byte -- write byte to LCD
44350 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
44351 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
44352 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
44353 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
44354 COLON \ high level word starts here
44355 TOP_LCD 2 20_US \ write high nibble first
44360 CODE LCD_WrC \ char -- Write Char
44361 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44366 CODE LCD_WrF \ func -- Write Fonction
44367 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44373 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
44378 $02 LCD_WrF 100 20_us
44382 \ : LCD_Entry_set $04 OR LCD_WrF ;
44384 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
44386 \ : LCD_Display_Shift $10 OR LCD_WrF ;
44388 \ : LCD_Fn_Set $20 OR LCD_WrF ;
44390 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
44392 \ : LCD_Goto $80 OR LCD_WrF ;
44394 \ CODE LCD_R \ -- byte read byte from LCD
44395 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
44396 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
44397 \ COLON \ starts a FORTH word
44398 \ TOP_LCD 2 20_us \ -- %0000HHHH
44399 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
44400 \ HI2LO \ switch from FORTH to assembler
44401 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
44402 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
44403 \ MOV @RSP+,IP \ restore IP saved by COLON
44408 \ CODE LCD_RdS \ -- status Read Status
44409 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44414 \ CODE LCD_RdC \ -- char Read Char
44415 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44420 \ -------------+------+------+------+------++---+---+---+---+---------+
44421 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
44422 \ -------------+------+------+------+------++---+---+---+---+---------+
44423 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
44424 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
44425 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
44426 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
44427 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
44428 \ -------------+------+------+------+------++---+---+---+---+---------+
44431 \ ******************************\
44432 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44433 \ ******************************\
44434 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
44435 \ ------------------------------\
44436 \ define LPM mode for ACCEPT \
44437 \ ------------------------------\
44438 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44439 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44440 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44441 BIT.B #SW2,&SW2_IN \ test switch S2
44442 0= IF \ case of switch S2 pressed
44443 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
44445 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
44448 BIT.B #SW1,&SW1_IN \ test switch S1 input
44449 0= IF \ case of Switch S1 pressed
44450 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
44452 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
44456 RETI \ CPU is ON, GIE is OFF
44461 \ ------------------------------\
44462 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44463 \ ******************************\
44464 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44465 \ ******************************\
44466 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44467 \ \ SMclock = 8|16|24 MHz
44468 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
44469 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
44470 \ \ SR(9)=new Toggle bit memory (ADD on)
44471 \ ------------------------------\
44472 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
44473 \ ------------------------------\
44474 \ define LPM mode for ACCEPT \
44475 \ ------------------------------\
44476 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44477 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44478 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44479 \ ------------------------------\
44480 \ RC5_FirstStartBitHalfCycle: \
44481 \ ------------------------------\
44482 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
44483 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
44484 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
44485 MOV #1778,X \ RC5_Period in us
44486 MOV #14,W \ count of loop
44488 \ ------------------------------\
44489 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
44490 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
44491 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
44492 \ RC5_Compute_3/4_Period: \ |
44493 RRUM #1,X \ X=1/2 cycle |
44497 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
44498 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
44500 \ ------------------------------\
44501 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
44502 \ ------------------------------\
44503 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44504 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
44505 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44506 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44507 SUB #1,W \ decrement count loop
44508 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
44509 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44510 0<> WHILE \ ----> out of loop ----+
44511 \ RC5_compute_7/4_Time_out: \ |
44512 ADD X,Y \ | out of bound = 7/4 period
44513 \ RC5_WaitHalfCycleP1.2_IFG: \ |
44515 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
44516 0>= IF \ | if cycle time out of bound
44517 BIC #$30,&TA0CTL \ | stop timer_A0
44518 RETI \ | then quit to do nothing
44520 \ ------------------------------\ |
44521 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
44523 MOV &TA0R,X \ | | get new RC5_period value
44524 REPEAT \ ----> loop back --+ |
44525 \ ------------------------------\ |
44526 \ RC5_SampleEndOf: \ <---------------------+
44527 \ ------------------------------\
44528 BIC #$30,&TA0CTL \ stop timer_A0
44529 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
44530 \ ******************************\
44531 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44532 \ ******************************\
44533 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
44534 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
44535 XOR IP,X \ (new XOR old) Toggle bit (13)
44536 BIT #BIT13,X \ X(13) = New_RC5_command
44537 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
44539 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
44540 \ ******************************\
44541 \ RC5_ComputeNewRC5word \
44542 \ ******************************\
44544 MOV &BASE,2(PSP) \ save variable BASE before use
44545 MOV TOS,0(PSP) \ save TOS before use
44546 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
44547 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
44548 \ ******************************\
44549 \ RC5_ComputeC6bit \
44550 \ ******************************\
44551 BIT #$4000,IP \ test /C6 bit in IP
44552 0= IF BIS #$40,TOS \ set C6 bit in S
44553 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
44554 \ ******************************\
44555 \ RC5_CommandByteIsDone \ RC5_code --
44556 \ ******************************\
44558 \ ------------------------------\
44559 \ Display IR_RC5 code \
44560 \ ------------------------------\
44561 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
44562 \ ------------------------------\
44563 LO2HI \ switch from assembler to FORTH
44564 ['] LCD_CLEAR IS CR \ redirects CR
44565 ['] LCD_WrC IS EMIT \ redirects EMIT
44566 $10 BASE ! \ change BASE to hexadecimal
44567 CR ." $" 2 U.R \ print IR_RC5 code
44568 ['] (CR) IS CR \ restore CR
44569 ['] (EMIT) IS EMIT \ restore EMIT
44570 HI2LO \ switch from FORTH to assembler
44571 \ ------------------------------\
44572 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
44573 \ ------------------------------\
44574 MOV @PSP+,&BASE \ restore variable BASE
44575 RETI \ CPU is ON, GIE is OFF
44580 \ ------------------------------\
44581 \ TB0CTL = %0000 0010 1001 0100\$3C0
44582 \ - - \CNTL Counter lentgh \ 00 = 16 bits
44583 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
44584 \ -- \ID input divider \ 10 = /4
44585 \ -- \MC Mode Control \ 01 = up to TB0CCR0
44586 \ - \TBCLR TimerB Clear
44589 \ --------------------------------\\
44590 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44591 \ -- \CM Capture Mode
44596 \ --- \OUTMOD \ 011 = set/reset
44602 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
44604 \ ------------------------------\
44605 \ set TimerB to make 50kHz PWM \
44606 \ ------------------------------\
44607 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44608 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
44609 \ ------------------------------\
44610 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
44611 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
44612 \ ------------------------------\
44613 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44614 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
44615 \ ------------------------------\
44616 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44617 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
44618 \ ------------------------------\
44619 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
44620 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
44621 \ ------------------------------\
44622 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
44623 \ ------------------------------\
44624 \ set TimerB to generate PWM for LCD_Vo
44625 \ ------------------------------\
44626 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
44627 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
44628 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
44629 \ ------------------------------\
44630 BIS.B #LCDVo,&LCDVo_DIR \
44631 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
44632 \ ------------------------------\
44633 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
44634 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
44635 \ ------------------------------\
44636 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
44637 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
44638 \ ------------------------------\
44639 \ WDT interval init part \
44640 \ ------------------------------\
44641 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
44642 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
44643 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
44644 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
44645 \ ------------------------------\
44647 \ ------------------------------\
44648 BIS.B #RC5,&IR_IE \ enable RC5_Int
44649 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
44650 \ ------------------------------\
44651 \ init interrupt vectors
44652 \ ------------------------------\
44653 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
44654 MOV #RC5_INT,&IR_Vec \ init interrupt vector
44655 \ ------------------------------\
44656 \ define LPM mode for ACCEPT \
44657 \ ------------------------------\
44658 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44659 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44660 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44662 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
44664 \ ------------------------------\
44666 \ ------------------------------\
44667 $03E8 20_US \ 1- wait 20 ms
44668 $03 TOP_LCD \ 2- send DB5=DB4=1
44669 $CD 20_US \ 3- wait 4,1 ms
44670 $03 TOP_LCD \ 4- send again DB5=DB4=1
44671 $5 20_US \ 5- wait 0,1 ms
44672 $03 TOP_LCD \ 6- send again again DB5=DB4=1
44673 $2 20_US \ wait 40 us = LCD cycle
44674 $02 TOP_LCD \ 7- send DB5=1 DB4=0
44675 $2 20_US \ wait 40 us = LCD cycle
44676 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
44677 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
44678 LCD_Clear \ 10- "LCD_Clear"
44679 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
44680 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
44681 LCD_Clear \ 10- "LCD_Clear"
44682 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
44683 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
44685 ['] (CR) IS CR \ ' (CR) is CR
44686 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
44688 ." RC5toLCD is running. Type STOP to quit"
44689 \ NOECHO \ uncomment to run this app without terminal connexion
44690 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
44691 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
44695 : STOP \ stops multitasking, must to be used before downloading app
44696 ['] (WARM) IS WARM \ remove START app from FORTH init process
44697 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
44705 CODE MAX \ n1 n2 -- n3 signed maximum
44706 CMP @PSP,TOS \ n2-n1
44707 S< ?GOTO FW1 \ n2<n1
44713 CODE MIN \ n1 n2 -- n3 signed minimum
44714 CMP @PSP,TOS \ n2-n1
44715 S< ?GOTO BW1 \ n2<n1
44721 : U.R \ u n -- display u unsigned in n width (n >= 2)
44723 R> OVER - 0 MAX SPACES TYPE
44727 CODE 20_US \ n -- n * 20 us
44728 BEGIN \ 3 cycles loop + 6~
44729 \ MOV #5,W \ 3 MCLK = 1 MHz
44730 \ MOV #23,W \ 3 MCLK = 4 MHz
44731 MOV #51,W \ 3 MCLK = 8 MHz
44732 \ MOV #104,W \ 3 MCLK = 16 MHz
44733 \ MOV #158,W \ 3 MCLK = 24 MHz
44734 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
44744 CODE TOP_LCD \ LCD Sample
44745 \ \ if write : %xxxxWWWW --
44746 \ \ if read : -- %0000RRRR
44747 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
44748 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
44749 0= IF \ write LCD bits pattern
44750 AND.B #LCD_DB,TOS \
44751 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
44752 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44755 THEN \ read LCD bits pattern
44758 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44759 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
44760 AND.B #LCD_DB,TOS \
44765 CODE LCD_W \ byte -- write byte to LCD
44767 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
44768 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
44769 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
44770 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
44771 COLON \ high level word starts here
44772 TOP_LCD 2 20_US \ write high nibble first
44777 CODE LCD_WrC \ char -- Write Char
44778 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44783 CODE LCD_WrF \ func -- Write Fonction
44784 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44790 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
44795 $02 LCD_WrF 100 20_us
44799 \ : LCD_Entry_set $04 OR LCD_WrF ;
44801 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
44803 \ : LCD_Display_Shift $10 OR LCD_WrF ;
44805 \ : LCD_Fn_Set $20 OR LCD_WrF ;
44807 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
44809 \ : LCD_Goto $80 OR LCD_WrF ;
44811 \ CODE LCD_R \ -- byte read byte from LCD
44812 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
44813 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
44814 \ COLON \ starts a FORTH word
44815 \ TOP_LCD 2 20_us \ -- %0000HHHH
44816 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
44817 \ HI2LO \ switch from FORTH to assembler
44818 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
44819 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
44820 \ MOV @RSP+,IP \ restore IP saved by COLON
44825 \ CODE LCD_RdS \ -- status Read Status
44826 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44831 \ CODE LCD_RdC \ -- char Read Char
44832 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44837 \ -------------+------+------+------+------++---+---+---+---+---------+
44838 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
44839 \ -------------+------+------+------+------++---+---+---+---+---------+
44840 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
44841 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
44842 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
44843 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
44844 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
44845 \ -------------+------+------+------+------++---+---+---+---+---------+
44848 \ ******************************\
44849 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44850 \ ******************************\
44851 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
44852 \ ------------------------------\
44853 \ define LPM mode for ACCEPT \
44854 \ ------------------------------\
44855 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44856 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44857 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44858 BIT.B #SW2,&SW2_IN \ test switch S2
44859 0= IF \ case of switch S2 pressed
44860 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
44862 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
44865 BIT.B #SW1,&SW1_IN \ test switch S1 input
44866 0= IF \ case of Switch S1 pressed
44867 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
44869 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
44873 RETI \ CPU is ON, GIE is OFF
44878 \ ------------------------------\
44879 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44880 \ ******************************\
44881 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44882 \ ******************************\
44883 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44884 \ \ SMclock = 8|16|24 MHz
44885 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
44886 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
44887 \ \ SR(9)=new Toggle bit memory (ADD on)
44888 \ ------------------------------\
44889 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
44890 \ ------------------------------\
44891 \ define LPM mode for ACCEPT \
44892 \ ------------------------------\
44893 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44894 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44895 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44896 \ ------------------------------\
44897 \ RC5_FirstStartBitHalfCycle: \
44898 \ ------------------------------\
44899 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
44900 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
44901 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
44902 MOV #1778,X \ RC5_Period in us
44903 MOV #14,W \ count of loop
44905 \ ------------------------------\
44906 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
44907 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
44908 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
44909 \ RC5_Compute_3/4_Period: \ |
44910 RRUM #1,X \ X=1/2 cycle |
44914 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
44915 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
44917 \ ------------------------------\
44918 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
44919 \ ------------------------------\
44920 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44921 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
44922 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44923 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44924 SUB #1,W \ decrement count loop
44925 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
44926 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44927 0<> WHILE \ ----> out of loop ----+
44928 \ RC5_compute_7/4_Time_out: \ |
44929 ADD X,Y \ | out of bound = 7/4 period
44930 \ RC5_WaitHalfCycleP1.2_IFG: \ |
44932 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
44933 0>= IF \ | if cycle time out of bound
44934 BIC #$30,&TA0CTL \ | stop timer_A0
44935 RETI \ | then quit to do nothing
44937 \ ------------------------------\ |
44938 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
44940 MOV &TA0R,X \ | | get new RC5_period value
44941 REPEAT \ ----> loop back --+ |
44942 \ ------------------------------\ |
44943 \ RC5_SampleEndOf: \ <---------------------+
44944 \ ------------------------------\
44945 BIC #$30,&TA0CTL \ stop timer_A0
44946 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
44947 \ ******************************\
44948 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44949 \ ******************************\
44950 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
44951 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
44952 XOR IP,X \ (new XOR old) Toggle bit (13)
44953 BIT #BIT13,X \ X(13) = New_RC5_command
44954 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
44956 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
44957 \ ******************************\
44958 \ RC5_ComputeNewRC5word \
44959 \ ******************************\
44961 MOV &BASE,2(PSP) \ save variable BASE before use
44962 MOV TOS,0(PSP) \ save TOS before use
44963 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
44964 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
44965 \ ******************************\
44966 \ RC5_ComputeC6bit \
44967 \ ******************************\
44968 BIT #$4000,IP \ test /C6 bit in IP
44969 0= IF BIS #$40,TOS \ set C6 bit in S
44970 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
44971 \ ******************************\
44972 \ RC5_CommandByteIsDone \ RC5_code --
44973 \ ******************************\
44975 \ ------------------------------\
44976 \ Display IR_RC5 code \
44977 \ ------------------------------\
44978 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
44979 \ ------------------------------\
44980 LO2HI \ switch from assembler to FORTH
44981 ['] LCD_CLEAR IS CR \ redirects CR
44982 ['] LCD_WrC IS EMIT \ redirects EMIT
44983 $10 BASE ! \ change BASE to hexadecimal
44984 CR ." $" 2 U.R \ print IR_RC5 code
44985 ['] (CR) IS CR \ restore CR
44986 ['] (EMIT) IS EMIT \ restore EMIT
44987 HI2LO \ switch from FORTH to assembler
44988 \ ------------------------------\
44989 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
44990 \ ------------------------------\
44991 MOV @PSP+,&BASE \ restore variable BASE
44992 RETI \ CPU is ON, GIE is OFF
44997 \ ------------------------------\
44998 \ TB0CTL = %0000 0010 1001 0100\$3C0
44999 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45000 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45001 \ -- \ID input divider \ 10 = /4
45002 \ -- \MC Mode Control \ 01 = up to TB0CCR0
45003 \ - \TBCLR TimerB Clear
45006 \ --------------------------------\\
45007 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45008 \ -- \CM Capture Mode
45013 \ --- \OUTMOD \ 011 = set/reset
45019 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
45021 \ ------------------------------\
45022 \ set TimerB to make 50kHz PWM \
45023 \ ------------------------------\
45024 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45025 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
45026 \ ------------------------------\
45027 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45028 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
45029 \ ------------------------------\
45030 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45031 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
45032 \ ------------------------------\
45033 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45034 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
45035 \ ------------------------------\
45036 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45037 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
45038 \ ------------------------------\
45039 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
45040 \ ------------------------------\
45041 \ set TimerB to generate PWM for LCD_Vo
45042 \ ------------------------------\
45043 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
45044 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
45045 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45046 \ ------------------------------\
45047 BIS.B #LCDVo,&LCDVo_DIR \
45048 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
45049 \ ------------------------------\
45050 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45051 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45052 \ ------------------------------\
45053 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45054 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45055 \ ------------------------------\
45056 \ WDT interval init part \
45057 \ ------------------------------\
45058 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
45059 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
45060 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
45061 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
45062 \ ------------------------------\
45064 \ ------------------------------\
45065 BIS.B #RC5,&IR_IE \ enable RC5_Int
45066 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45067 \ ------------------------------\
45068 \ init interrupt vectors
45069 \ ------------------------------\
45070 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
45071 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45072 \ ------------------------------\
45073 \ define LPM mode for ACCEPT \
45074 \ ------------------------------\
45075 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45076 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45077 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45079 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
45081 \ ------------------------------\
45083 \ ------------------------------\
45084 $03E8 20_US \ 1- wait 20 ms
45085 $03 TOP_LCD \ 2- send DB5=DB4=1
45086 $CD 20_US \ 3- wait 4,1 ms
45087 $03 TOP_LCD \ 4- send again DB5=DB4=1
45088 $5 20_US \ 5- wait 0,1 ms
45089 $03 TOP_LCD \ 6- send again again DB5=DB4=1
45090 $2 20_US \ wait 40 us = LCD cycle
45091 $02 TOP_LCD \ 7- send DB5=1 DB4=0
45092 $2 20_US \ wait 40 us = LCD cycle
45093 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45094 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45095 LCD_Clear \ 10- "LCD_Clear"
45096 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45097 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45098 LCD_Clear \ 10- "LCD_Clear"
45099 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45100 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45102 ['] (CR) IS CR \ ' (CR) is CR
45103 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
45105 ." RC5toLCD is running. Type STOP to quit"
45106 \ NOECHO \ uncomment to run this app without terminal connexion
45107 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
45108 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
45112 : STOP \ stops multitasking, must to be used before downloading app
45113 ['] (WARM) IS WARM \ remove START app from FORTH init process
45114 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
45122 CODE MAX \ n1 n2 -- n3 signed maximum
45123 CMP @PSP,TOS \ n2-n1
45124 S< ?GOTO FW1 \ n2<n1
45130 CODE MIN \ n1 n2 -- n3 signed minimum
45131 CMP @PSP,TOS \ n2-n1
45132 S< ?GOTO BW1 \ n2<n1
45138 : U.R \ u n -- display u unsigned in n width (n >= 2)
45140 R> OVER - 0 MAX SPACES TYPE
45144 CODE 20_US \ n -- n * 20 us
45145 BEGIN \ 3 cycles loop + 6~
45146 \ MOV #5,W \ 3 MCLK = 1 MHz
45147 \ MOV #23,W \ 3 MCLK = 4 MHz
45148 MOV #51,W \ 3 MCLK = 8 MHz
45149 \ MOV #104,W \ 3 MCLK = 16 MHz
45150 \ MOV #158,W \ 3 MCLK = 24 MHz
45151 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
45161 CODE TOP_LCD \ LCD Sample
45162 \ \ if write : %xxxxWWWW --
45163 \ \ if read : -- %0000RRRR
45164 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
45165 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
45166 0= IF \ write LCD bits pattern
45167 AND.B #LCD_DB,TOS \
45168 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
45169 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45172 THEN \ read LCD bits pattern
45175 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45176 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
45177 AND.B #LCD_DB,TOS \
45182 CODE LCD_W \ byte -- write byte to LCD
45184 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
45185 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
45186 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
45187 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
45188 COLON \ high level word starts here
45189 TOP_LCD 2 20_US \ write high nibble first
45194 CODE LCD_WrC \ char -- Write Char
45195 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45200 CODE LCD_WrF \ func -- Write Fonction
45201 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45207 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
45212 $02 LCD_WrF 100 20_us
45216 \ : LCD_Entry_set $04 OR LCD_WrF ;
45218 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
45220 \ : LCD_Display_Shift $10 OR LCD_WrF ;
45222 \ : LCD_Fn_Set $20 OR LCD_WrF ;
45224 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
45226 \ : LCD_Goto $80 OR LCD_WrF ;
45228 \ CODE LCD_R \ -- byte read byte from LCD
45229 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
45230 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
45231 \ COLON \ starts a FORTH word
45232 \ TOP_LCD 2 20_us \ -- %0000HHHH
45233 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
45234 \ HI2LO \ switch from FORTH to assembler
45235 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
45236 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
45237 \ MOV @RSP+,IP \ restore IP saved by COLON
45242 \ CODE LCD_RdS \ -- status Read Status
45243 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45248 \ CODE LCD_RdC \ -- char Read Char
45249 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45254 \ -------------+------+------+------+------++---+---+---+---+---------+
45255 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
45256 \ -------------+------+------+------+------++---+---+---+---+---------+
45257 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
45258 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
45259 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
45260 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
45261 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
45262 \ -------------+------+------+------+------++---+---+---+---+---------+
45265 \ ******************************\
45266 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
45267 \ ******************************\
45268 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
45269 \ ------------------------------\
45270 \ define LPM mode for ACCEPT \
45271 \ ------------------------------\
45272 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45273 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45274 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45275 BIT.B #SW2,&SW2_IN \ test switch S2
45276 0= IF \ case of switch S2 pressed
45277 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
45279 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
45282 BIT.B #SW1,&SW1_IN \ test switch S1 input
45283 0= IF \ case of Switch S1 pressed
45284 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
45286 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
45290 RETI \ CPU is ON, GIE is OFF
45295 \ ------------------------------\
45296 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
45297 \ ******************************\
45298 ASM RC5_INT \ wake up on Px.RC5 change interrupt
45299 \ ******************************\
45300 \ \ in : SR(9)=old Toggle bit memory (ADD on)
45301 \ \ SMclock = 8|16|24 MHz
45302 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
45303 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
45304 \ \ SR(9)=new Toggle bit memory (ADD on)
45305 \ ------------------------------\
45306 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
45307 \ ------------------------------\
45308 \ define LPM mode for ACCEPT \
45309 \ ------------------------------\
45310 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45311 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45312 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45313 \ ------------------------------\
45314 \ RC5_FirstStartBitHalfCycle: \
45315 \ ------------------------------\
45316 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
45317 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
45318 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
45319 MOV #1778,X \ RC5_Period in us
45320 MOV #14,W \ count of loop
45322 \ ------------------------------\
45323 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
45324 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
45325 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
45326 \ RC5_Compute_3/4_Period: \ |
45327 RRUM #1,X \ X=1/2 cycle |
45331 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
45332 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
45334 \ ------------------------------\
45335 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
45336 \ ------------------------------\
45337 BIT.B #RC5,&IR_IN \ C_flag = IR bit
45338 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
45339 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
45340 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
45341 SUB #1,W \ decrement count loop
45342 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
45343 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
45344 0<> WHILE \ ----> out of loop ----+
45345 \ RC5_compute_7/4_Time_out: \ |
45346 ADD X,Y \ | out of bound = 7/4 period
45347 \ RC5_WaitHalfCycleP1.2_IFG: \ |
45349 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
45350 0>= IF \ | if cycle time out of bound
45351 BIC #$30,&TA0CTL \ | stop timer_A0
45352 RETI \ | then quit to do nothing
45354 \ ------------------------------\ |
45355 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
45357 MOV &TA0R,X \ | | get new RC5_period value
45358 REPEAT \ ----> loop back --+ |
45359 \ ------------------------------\ |
45360 \ RC5_SampleEndOf: \ <---------------------+
45361 \ ------------------------------\
45362 BIC #$30,&TA0CTL \ stop timer_A0
45363 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
45364 \ ******************************\
45365 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
45366 \ ******************************\
45367 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
45368 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
45369 XOR IP,X \ (new XOR old) Toggle bit (13)
45370 BIT #BIT13,X \ X(13) = New_RC5_command
45371 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
45373 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
45374 \ ******************************\
45375 \ RC5_ComputeNewRC5word \
45376 \ ******************************\
45378 MOV &BASE,2(PSP) \ save variable BASE before use
45379 MOV TOS,0(PSP) \ save TOS before use
45380 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
45381 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
45382 \ ******************************\
45383 \ RC5_ComputeC6bit \
45384 \ ******************************\
45385 BIT #$4000,IP \ test /C6 bit in IP
45386 0= IF BIS #$40,TOS \ set C6 bit in S
45387 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
45388 \ ******************************\
45389 \ RC5_CommandByteIsDone \ RC5_code --
45390 \ ******************************\
45392 \ ------------------------------\
45393 \ Display IR_RC5 code \
45394 \ ------------------------------\
45395 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
45396 \ ------------------------------\
45397 LO2HI \ switch from assembler to FORTH
45398 ['] LCD_CLEAR IS CR \ redirects CR
45399 ['] LCD_WrC IS EMIT \ redirects EMIT
45400 $10 BASE ! \ change BASE to hexadecimal
45401 CR ." $" 2 U.R \ print IR_RC5 code
45402 ['] (CR) IS CR \ restore CR
45403 ['] (EMIT) IS EMIT \ restore EMIT
45404 HI2LO \ switch from FORTH to assembler
45405 \ ------------------------------\
45406 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
45407 \ ------------------------------\
45408 MOV @PSP+,&BASE \ restore variable BASE
45409 RETI \ CPU is ON, GIE is OFF
45414 \ ------------------------------\
45415 \ TB0CTL = %0000 0010 1001 0100\$3C0
45416 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45417 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45418 \ -- \ID input divider \ 10 = /4
45419 \ -- \MC Mode Control \ 01 = up to TB0CCR0
45420 \ - \TBCLR TimerB Clear
45423 \ --------------------------------\\
45424 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45425 \ -- \CM Capture Mode
45430 \ --- \OUTMOD \ 011 = set/reset
45436 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
45438 \ ------------------------------\
45439 \ set TimerB to make 50kHz PWM \
45440 \ ------------------------------\
45441 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45442 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
45443 \ ------------------------------\
45444 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45445 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
45446 \ ------------------------------\
45447 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45448 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
45449 \ ------------------------------\
45450 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45451 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
45452 \ ------------------------------\
45453 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45454 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
45455 \ ------------------------------\
45456 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
45457 \ ------------------------------\
45458 \ set TimerB to generate PWM for LCD_Vo
45459 \ ------------------------------\
45460 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
45461 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
45462 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45463 \ ------------------------------\
45464 BIS.B #LCDVo,&LCDVo_DIR \
45465 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
45466 \ ------------------------------\
45467 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45468 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45469 \ ------------------------------\
45470 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45471 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45472 \ ------------------------------\
45473 \ WDT interval init part \
45474 \ ------------------------------\
45475 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
45476 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
45477 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
45478 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
45479 \ ------------------------------\
45481 \ ------------------------------\
45482 BIS.B #RC5,&IR_IE \ enable RC5_Int
45483 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45484 \ ------------------------------\
45485 \ init interrupt vectors
45486 \ ------------------------------\
45487 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
45488 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45489 \ ------------------------------\
45490 \ define LPM mode for ACCEPT \
45491 \ ------------------------------\
45492 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45493 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45494 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45496 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
45498 \ ------------------------------\
45500 \ ------------------------------\
45501 $03E8 20_US \ 1- wait 20 ms
45502 $03 TOP_LCD \ 2- send DB5=DB4=1
45503 $CD 20_US \ 3- wait 4,1 ms
45504 $03 TOP_LCD \ 4- send again DB5=DB4=1
45505 $5 20_US \ 5- wait 0,1 ms
45506 $03 TOP_LCD \ 6- send again again DB5=DB4=1
45507 $2 20_US \ wait 40 us = LCD cycle
45508 $02 TOP_LCD \ 7- send DB5=1 DB4=0
45509 $2 20_US \ wait 40 us = LCD cycle
45510 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45511 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45512 LCD_Clear \ 10- "LCD_Clear"
45513 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45514 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45515 LCD_Clear \ 10- "LCD_Clear"
45516 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45517 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45519 ['] (CR) IS CR \ ' (CR) is CR
45520 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
45522 ." RC5toLCD is running. Type STOP to quit"
45523 \ NOECHO \ uncomment to run this app without terminal connexion
45524 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
45525 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
45529 : STOP \ stops multitasking, must to be used before downloading app
45530 ['] (WARM) IS WARM \ remove START app from FORTH init process
45531 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
45539 CODE MAX \ n1 n2 -- n3 signed maximum
45540 CMP @PSP,TOS \ n2-n1
45541 S< ?GOTO FW1 \ n2<n1
45547 CODE MIN \ n1 n2 -- n3 signed minimum
45548 CMP @PSP,TOS \ n2-n1
45549 S< ?GOTO BW1 \ n2<n1
45555 : U.R \ u n -- display u unsigned in n width (n >= 2)
45557 R> OVER - 0 MAX SPACES TYPE
45561 CODE 20_US \ n -- n * 20 us
45562 BEGIN \ 3 cycles loop + 6~
45563 \ MOV #5,W \ 3 MCLK = 1 MHz
45564 \ MOV #23,W \ 3 MCLK = 4 MHz
45565 MOV #51,W \ 3 MCLK = 8 MHz
45566 \ MOV #104,W \ 3 MCLK = 16 MHz
45567 \ MOV #158,W \ 3 MCLK = 24 MHz
45568 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
45578 CODE TOP_LCD \ LCD Sample
45579 \ \ if write : %xxxxWWWW --
45580 \ \ if read : -- %0000RRRR
45581 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
45582 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
45583 0= IF \ write LCD bits pattern
45584 AND.B #LCD_DB,TOS \
45585 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
45586 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45589 THEN \ read LCD bits pattern
45592 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45593 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
45594 AND.B #LCD_DB,TOS \
45599 CODE LCD_W \ byte -- write byte to LCD
45601 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
45602 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
45603 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
45604 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
45605 COLON \ high level word starts here
45606 TOP_LCD 2 20_US \ write high nibble first
45611 CODE LCD_WrC \ char -- Write Char
45612 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45617 CODE LCD_WrF \ func -- Write Fonction
45618 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45624 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
45629 $02 LCD_WrF 100 20_us
45633 \ : LCD_Entry_set $04 OR LCD_WrF ;
45635 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
45637 \ : LCD_Display_Shift $10 OR LCD_WrF ;
45639 \ : LCD_Fn_Set $20 OR LCD_WrF ;
45641 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
45643 \ : LCD_Goto $80 OR LCD_WrF ;
45645 \ CODE LCD_R \ -- byte read byte from LCD
45646 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
45647 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
45648 \ COLON \ starts a FORTH word
45649 \ TOP_LCD 2 20_us \ -- %0000HHHH
45650 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
45651 \ HI2LO \ switch from FORTH to assembler
45652 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
45653 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
45654 \ MOV @RSP+,IP \ restore IP saved by COLON
45659 \ CODE LCD_RdS \ -- status Read Status
45660 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45665 \ CODE LCD_RdC \ -- char Read Char
45666 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45671 \ -------------+------+------+------+------++---+---+---+---+---------+
45672 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
45673 \ -------------+------+------+------+------++---+---+---+---+---------+
45674 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
45675 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
45676 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
45677 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
45678 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
45679 \ -------------+------+------+------+------++---+---+---+---+---------+
45682 \ ******************************\
45683 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
45684 \ ******************************\
45685 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
45686 \ ------------------------------\
45687 \ define LPM mode for ACCEPT \
45688 \ ------------------------------\
45689 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45690 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45691 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45692 BIT.B #SW2,&SW2_IN \ test switch S2
45693 0= IF \ case of switch S2 pressed
45694 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
45696 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
45699 BIT.B #SW1,&SW1_IN \ test switch S1 input
45700 0= IF \ case of Switch S1 pressed
45701 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
45703 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
45707 RETI \ CPU is ON, GIE is OFF
45712 \ ------------------------------\
45713 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
45714 \ ******************************\
45715 ASM RC5_INT \ wake up on Px.RC5 change interrupt
45716 \ ******************************\
45717 \ \ in : SR(9)=old Toggle bit memory (ADD on)
45718 \ \ SMclock = 8|16|24 MHz
45719 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
45720 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
45721 \ \ SR(9)=new Toggle bit memory (ADD on)
45722 \ ------------------------------\
45723 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
45724 \ ------------------------------\
45725 \ define LPM mode for ACCEPT \
45726 \ ------------------------------\
45727 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45728 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45729 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45730 \ ------------------------------\
45731 \ RC5_FirstStartBitHalfCycle: \
45732 \ ------------------------------\
45733 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
45734 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
45735 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
45736 MOV #1778,X \ RC5_Period in us
45737 MOV #14,W \ count of loop
45739 \ ------------------------------\
45740 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
45741 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
45742 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
45743 \ RC5_Compute_3/4_Period: \ |
45744 RRUM #1,X \ X=1/2 cycle |
45748 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
45749 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
45751 \ ------------------------------\
45752 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
45753 \ ------------------------------\
45754 BIT.B #RC5,&IR_IN \ C_flag = IR bit
45755 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
45756 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
45757 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
45758 SUB #1,W \ decrement count loop
45759 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
45760 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
45761 0<> WHILE \ ----> out of loop ----+
45762 \ RC5_compute_7/4_Time_out: \ |
45763 ADD X,Y \ | out of bound = 7/4 period
45764 \ RC5_WaitHalfCycleP1.2_IFG: \ |
45766 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
45767 0>= IF \ | if cycle time out of bound
45768 BIC #$30,&TA0CTL \ | stop timer_A0
45769 RETI \ | then quit to do nothing
45771 \ ------------------------------\ |
45772 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
45774 MOV &TA0R,X \ | | get new RC5_period value
45775 REPEAT \ ----> loop back --+ |
45776 \ ------------------------------\ |
45777 \ RC5_SampleEndOf: \ <---------------------+
45778 \ ------------------------------\
45779 BIC #$30,&TA0CTL \ stop timer_A0
45780 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
45781 \ ******************************\
45782 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
45783 \ ******************************\
45784 MOV @RSP,X \ retiSR(9) = old UF1 = old RC5 toggle bit
45785 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
45786 XOR IP,X \ (new XOR old) Toggle bit (13)
45787 BIT #BIT13,X \ X(13) = New_RC5_command
45788 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
45790 XOR #UF1,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
45791 \ ******************************\
45792 \ RC5_ComputeNewRC5word \
45793 \ ******************************\
45795 MOV &BASE,2(PSP) \ save variable BASE before use
45796 MOV TOS,0(PSP) \ save TOS before use
45797 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
45798 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
45799 \ ******************************\
45800 \ RC5_ComputeC6bit \
45801 \ ******************************\
45802 BIT #$4000,IP \ test /C6 bit in IP
45803 0= IF BIS #$40,TOS \ set C6 bit in S
45804 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
45805 \ ******************************\
45806 \ RC5_CommandByteIsDone \ RC5_code --
45807 \ ******************************\
45809 \ ------------------------------\
45810 \ Display IR_RC5 code \
45811 \ ------------------------------\
45812 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
45813 \ ------------------------------\
45814 LO2HI \ switch from assembler to FORTH
45815 ['] LCD_CLEAR IS CR \ redirects CR
45816 ['] LCD_WrC IS EMIT \ redirects EMIT
45817 $10 BASE ! \ change BASE to hexadecimal
45818 CR ." $" 2 U.R \ print IR_RC5 code
45819 ['] (CR) IS CR \ restore CR
45820 ['] (EMIT) IS EMIT \ restore EMIT
45821 HI2LO \ switch from FORTH to assembler
45822 \ ------------------------------\
45823 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
45824 \ ------------------------------\
45825 MOV @PSP+,&BASE \ restore variable BASE
45826 RETI \ CPU is ON, GIE is OFF
45831 \ ------------------------------\
45832 \ TB0CTL = %0000 0010 1001 0100\$3C0
45833 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45834 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45835 \ -- \ID input divider \ 10 = /4
45836 \ -- \MC Mode Control \ 01 = up to TB0CCR0
45837 \ - \TBCLR TimerB Clear
45840 \ --------------------------------\\
45841 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45842 \ -- \CM Capture Mode
45847 \ --- \OUTMOD \ 011 = set/reset
45853 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
45855 \ ------------------------------\
45856 \ set TimerB to make 50kHz PWM \
45857 \ ------------------------------\
45858 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45859 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
45860 \ ------------------------------\
45861 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
45862 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
45863 \ ------------------------------\
45864 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45865 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
45866 \ ------------------------------\
45867 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45868 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
45869 \ ------------------------------\
45870 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
45871 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
45872 \ ------------------------------\
45873 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
45874 \ ------------------------------\
45875 \ set TimerB to generate PWM for LCD_Vo
45876 \ ------------------------------\
45877 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
45878 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
45879 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45880 \ ------------------------------\
45881 BIS.B #LCDVo,&LCDVo_DIR \
45882 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
45883 \ ------------------------------\
45884 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45885 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45886 \ ------------------------------\
45887 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45888 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45889 \ ------------------------------\
45890 \ WDT interval init part \
45891 \ ------------------------------\
45892 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
45893 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
45894 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
45895 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
45896 \ ------------------------------\
45898 \ ------------------------------\
45899 BIS.B #RC5,&IR_IE \ enable RC5_Int
45900 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45901 \ ------------------------------\
45902 \ init interrupt vectors
45903 \ ------------------------------\
45904 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
45905 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45906 \ ------------------------------\
45907 \ define LPM mode for ACCEPT \
45908 \ ------------------------------\
45909 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45910 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45911 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45913 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
45915 \ ------------------------------\
45917 \ ------------------------------\
45918 $03E8 20_US \ 1- wait 20 ms
45919 $03 TOP_LCD \ 2- send DB5=DB4=1
45920 $CD 20_US \ 3- wait 4,1 ms
45921 $03 TOP_LCD \ 4- send again DB5=DB4=1
45922 $5 20_US \ 5- wait 0,1 ms
45923 $03 TOP_LCD \ 6- send again again DB5=DB4=1
45924 $2 20_US \ wait 40 us = LCD cycle
45925 $02 TOP_LCD \ 7- send DB5=1 DB4=0
45926 $2 20_US \ wait 40 us = LCD cycle
45927 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45928 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45929 LCD_Clear \ 10- "LCD_Clear"
45930 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45931 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45932 LCD_Clear \ 10- "LCD_Clear"
45933 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45934 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45936 ['] (CR) IS CR \ ' (CR) is CR
45937 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
45939 ." RC5toLCD is running. Type STOP to quit"
45940 \ NOECHO \ uncomment to run this app without terminal connexion
45941 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
45942 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
45946 : STOP \ stops multitasking, must to be used before downloading app
45947 ['] (WARM) IS WARM \ remove START app from FORTH init process
45948 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
45956 RST_HERE ; this app is protected against <reset>,