1 ; -----------------------------------
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)
89 CODE MAX \ n1 n2 -- n3 signed maximum
97 CODE MIN \ n1 n2 -- n3 signed minimum
105 : U.R \ u n -- display u unsigned in n width (n >= 2)
107 R> OVER - 0 MAX SPACES TYPE
111 CODE 20_US \ n -- n * 20 us
112 BEGIN \ 3 cycles loop + 6~
113 \ MOV #5,W \ 3 MCLK = 1 MHz
114 \ MOV #23,W \ 3 MCLK = 4 MHz
115 MOV #51,W \ 3 MCLK = 8 MHz
116 \ MOV #104,W \ 3 MCLK = 16 MHz
117 \ MOV #158,W \ 3 MCLK = 24 MHz
118 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
128 CODE TOP_LCD \ LCD Sample
129 \ \ if write : %xxxxWWWW --
130 \ \ if read : -- %0000RRRR
131 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
132 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
133 0= IF \ write LCD bits pattern
135 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
136 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
139 THEN \ read LCD bits pattern
142 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
143 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
149 CODE LCD_W \ byte -- write byte to LCD
151 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
152 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
153 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
154 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
155 COLON \ high level word starts here
156 TOP_LCD 2 20_US \ write high nibble first
161 CODE LCD_WrC \ char -- Write Char
162 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
167 CODE LCD_WrF \ func -- Write Fonction
168 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
174 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
179 $02 LCD_WrF 100 20_us
183 \ : LCD_Entry_set $04 OR LCD_WrF ;
185 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
187 \ : LCD_Display_Shift $10 OR LCD_WrF ;
189 \ : LCD_Fn_Set $20 OR LCD_WrF ;
191 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
193 \ : LCD_Goto $80 OR LCD_WrF ;
195 \ CODE LCD_R \ -- byte read byte from LCD
196 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
197 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
198 \ COLON \ starts a FORTH word
199 \ TOP_LCD 2 20_us \ -- %0000HHHH
200 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
201 \ HI2LO \ switch from FORTH to assembler
202 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
203 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
204 \ MOV @RSP+,IP \ restore IP saved by COLON
209 \ CODE LCD_RdS \ -- status Read Status
210 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
215 \ CODE LCD_RdC \ -- char Read Char
216 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
221 \ -------------+------+------+------+------++---+---+---+---+---------+
222 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
223 \ -------------+------+------+------+------++---+---+---+---+---------+
224 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
225 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
226 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
227 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
228 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
229 \ -------------+------+------+------+------++---+---+---+---+---------+
232 \ ******************************\
233 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
234 \ ******************************\
235 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
236 \ ------------------------------\
237 \ define LPM mode for ACCEPT \
238 \ ------------------------------\
239 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
240 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
241 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
242 BIT.B #SW2,&SW2_IN \ test switch S2
243 0= IF \ case of switch S2 pressed
244 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
246 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
249 BIT.B #SW1,&SW1_IN \ test switch S1 input
250 0= IF \ case of Switch S1 pressed
251 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
253 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
257 RETI \ CPU is ON, GIE is OFF
262 \ ------------------------------\
263 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
264 \ ******************************\
265 ASM RC5_INT \ wake up on Px.RC5 change interrupt
266 \ ******************************\
267 \ \ in : SR(9)=old Toggle bit memory (ADD on)
268 \ \ SMclock = 8|16|24 MHz
269 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
270 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
271 \ \ SR(9)=new Toggle bit memory (ADD on)
272 \ ------------------------------\
273 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
274 \ ------------------------------\
275 \ define LPM mode for ACCEPT \
276 \ ------------------------------\
277 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
278 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
279 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
280 \ ------------------------------\
281 \ RC5_FirstStartBitHalfCycle: \
282 \ ------------------------------\
283 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
284 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
285 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
286 MOV #1778,X \ RC5_Period in us
287 MOV #14,W \ count of loop
289 \ ------------------------------\
290 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
291 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
292 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
293 \ RC5_Compute_3/4_Period: \ |
294 RRUM #1,X \ X=1/2 cycle |
298 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
299 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
301 \ ------------------------------\
302 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
303 \ ------------------------------\
304 BIT.B #RC5,&IR_IN \ C_flag = IR bit
305 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
306 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
307 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
308 SUB #1,W \ decrement count loop
309 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
310 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
311 0<> WHILE \ ----> out of loop ----+
312 \ RC5_compute_7/4_Time_out: \ |
313 ADD X,Y \ | out of bound = 7/4 period
314 \ RC5_WaitHalfCycleP1.2_IFG: \ |
316 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
317 0>= IF \ | if cycle time out of bound
318 BIC #$30,&TA0CTL \ | stop timer_A0
319 RETI \ | then quit to do nothing
321 \ ------------------------------\ |
322 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
324 MOV &TA0R,X \ | | get new RC5_period value
325 REPEAT \ ----> loop back --+ |
326 \ ------------------------------\ |
327 \ RC5_SampleEndOf: \ <---------------------+
328 \ ------------------------------\
329 BIC #$30,&TA0CTL \ stop timer_A0
330 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
331 \ ******************************\
332 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
333 \ ******************************\
334 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
335 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
336 XOR IP,X \ (new XOR old) Toggle bit (13)
337 BIT #BIT13,X \ X(13) = New_RC5_command
338 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
340 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
341 \ ******************************\
342 \ RC5_ComputeNewRC5word \
343 \ ******************************\
345 MOV &BASE,2(PSP) \ save variable BASE before use
346 MOV TOS,0(PSP) \ save TOS before use
347 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
348 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
349 \ ******************************\
351 \ ******************************\
352 BIT #$4000,IP \ test /C6 bit in IP
353 0= IF BIS #$40,TOS \ set C6 bit in S
354 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
355 \ ******************************\
356 \ RC5_CommandByteIsDone \ RC5_code --
357 \ ******************************\
359 \ ------------------------------\
360 \ Display IR_RC5 code \
361 \ ------------------------------\
362 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
363 \ ------------------------------\
364 LO2HI \ switch from assembler to FORTH
365 ['] LCD_CLEAR IS CR \ redirects CR
366 ['] LCD_WrC IS EMIT \ redirects EMIT
367 $10 BASE ! \ change BASE to hexadecimal
368 CR ." $" 2 U.R \ print IR_RC5 code
369 ['] (CR) IS CR \ restore CR
370 ['] (EMIT) IS EMIT \ restore EMIT
371 HI2LO \ switch from FORTH to assembler
372 \ ------------------------------\
373 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
374 \ ------------------------------\
375 MOV @PSP+,&BASE \ restore variable BASE
376 RETI \ CPU is ON, GIE is OFF
381 \ ------------------------------\
382 \ TB0CTL = %0000 0010 1001 0100\$3C0
383 \ - - \CNTL Counter lentgh \ 00 = 16 bits
384 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
385 \ -- \ID input divider \ 10 = /4
386 \ -- \MC Mode Control \ 01 = up to TB0CCR0
387 \ - \TBCLR TimerB Clear
390 \ --------------------------------\\
391 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
392 \ -- \CM Capture Mode
397 \ --- \OUTMOD \ 011 = set/reset
403 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
405 \ ------------------------------\
406 \ set TimerB to make 50kHz PWM \
407 \ ------------------------------\
408 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
409 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
410 \ ------------------------------\
411 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
412 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
413 \ ------------------------------\
414 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
415 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
416 \ ------------------------------\
417 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
418 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
419 \ ------------------------------\
420 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
421 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
422 \ ------------------------------\
423 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
424 \ ------------------------------\
425 \ set TimerB to generate PWM for LCD_Vo
426 \ ------------------------------\
427 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
428 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
429 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
430 \ ------------------------------\
431 BIS.B #LCDVo,&LCDVo_DIR \
432 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
433 \ ------------------------------\
434 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
435 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
436 \ ------------------------------\
437 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
438 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
439 \ ------------------------------\
440 \ WDT interval init part \
441 \ ------------------------------\
442 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
443 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
444 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
445 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
446 \ ------------------------------\
448 \ ------------------------------\
449 BIS.B #RC5,&IR_IE \ enable RC5_Int
450 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
451 \ ------------------------------\
452 \ init interrupt vectors
453 \ ------------------------------\
454 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
455 MOV #RC5_INT,&IR_Vec \ init interrupt vector
456 \ ------------------------------\
457 \ define LPM mode for ACCEPT \
458 \ ------------------------------\
459 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
460 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
461 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
463 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
465 \ ------------------------------\
467 \ ------------------------------\
468 $03E8 20_US \ 1- wait 20 ms
469 $03 TOP_LCD \ 2- send DB5=DB4=1
470 $CD 20_US \ 3- wait 4,1 ms
471 $03 TOP_LCD \ 4- send again DB5=DB4=1
472 $5 20_US \ 5- wait 0,1 ms
473 $03 TOP_LCD \ 6- send again again DB5=DB4=1
474 $2 20_US \ wait 40 us = LCD cycle
475 $02 TOP_LCD \ 7- send DB5=1 DB4=0
476 $2 20_US \ wait 40 us = LCD cycle
477 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
478 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
479 LCD_Clear \ 10- "LCD_Clear"
480 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
481 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
482 LCD_Clear \ 10- "LCD_Clear"
483 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
484 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
486 ['] (CR) IS CR \ ' (CR) is CR
487 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
489 ." RC5toLCD is running. Type STOP to quit"
490 \ NOECHO \ uncomment to run this app without terminal connexion
491 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
492 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
496 : STOP \ stops multitasking, must to be used before downloading app
497 ['] (WARM) IS WARM \ remove START app from FORTH init process
498 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
506 CODE MAX \ n1 n2 -- n3 signed maximum
514 CODE MIN \ n1 n2 -- n3 signed minimum
522 : U.R \ u n -- display u unsigned in n width (n >= 2)
524 R> OVER - 0 MAX SPACES TYPE
528 CODE 20_US \ n -- n * 20 us
529 BEGIN \ 3 cycles loop + 6~
530 \ MOV #5,W \ 3 MCLK = 1 MHz
531 \ MOV #23,W \ 3 MCLK = 4 MHz
532 MOV #51,W \ 3 MCLK = 8 MHz
533 \ MOV #104,W \ 3 MCLK = 16 MHz
534 \ MOV #158,W \ 3 MCLK = 24 MHz
535 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
545 CODE TOP_LCD \ LCD Sample
546 \ \ if write : %xxxxWWWW --
547 \ \ if read : -- %0000RRRR
548 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
549 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
550 0= IF \ write LCD bits pattern
552 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
553 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
556 THEN \ read LCD bits pattern
559 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
560 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
566 CODE LCD_W \ byte -- write byte to LCD
568 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
569 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
570 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
571 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
572 COLON \ high level word starts here
573 TOP_LCD 2 20_US \ write high nibble first
578 CODE LCD_WrC \ char -- Write Char
579 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
584 CODE LCD_WrF \ func -- Write Fonction
585 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
591 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
596 $02 LCD_WrF 100 20_us
600 \ : LCD_Entry_set $04 OR LCD_WrF ;
602 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
604 \ : LCD_Display_Shift $10 OR LCD_WrF ;
606 \ : LCD_Fn_Set $20 OR LCD_WrF ;
608 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
610 \ : LCD_Goto $80 OR LCD_WrF ;
612 \ CODE LCD_R \ -- byte read byte from LCD
613 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
614 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
615 \ COLON \ starts a FORTH word
616 \ TOP_LCD 2 20_us \ -- %0000HHHH
617 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
618 \ HI2LO \ switch from FORTH to assembler
619 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
620 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
621 \ MOV @RSP+,IP \ restore IP saved by COLON
626 \ CODE LCD_RdS \ -- status Read Status
627 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
632 \ CODE LCD_RdC \ -- char Read Char
633 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
638 \ -------------+------+------+------+------++---+---+---+---+---------+
639 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
640 \ -------------+------+------+------+------++---+---+---+---+---------+
641 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
642 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
643 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
644 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
645 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
646 \ -------------+------+------+------+------++---+---+---+---+---------+
649 \ ******************************\
650 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
651 \ ******************************\
652 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
653 \ ------------------------------\
654 \ define LPM mode for ACCEPT \
655 \ ------------------------------\
656 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
657 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
658 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
659 BIT.B #SW2,&SW2_IN \ test switch S2
660 0= IF \ case of switch S2 pressed
661 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
663 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
666 BIT.B #SW1,&SW1_IN \ test switch S1 input
667 0= IF \ case of Switch S1 pressed
668 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
670 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
674 RETI \ CPU is ON, GIE is OFF
679 \ ------------------------------\
680 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
681 \ ******************************\
682 ASM RC5_INT \ wake up on Px.RC5 change interrupt
683 \ ******************************\
684 \ \ in : SR(9)=old Toggle bit memory (ADD on)
685 \ \ SMclock = 8|16|24 MHz
686 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
687 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
688 \ \ SR(9)=new Toggle bit memory (ADD on)
689 \ ------------------------------\
690 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
691 \ ------------------------------\
692 \ define LPM mode for ACCEPT \
693 \ ------------------------------\
694 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
695 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
696 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
697 \ ------------------------------\
698 \ RC5_FirstStartBitHalfCycle: \
699 \ ------------------------------\
700 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
701 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
702 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
703 MOV #1778,X \ RC5_Period in us
704 MOV #14,W \ count of loop
706 \ ------------------------------\
707 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
708 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
709 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
710 \ RC5_Compute_3/4_Period: \ |
711 RRUM #1,X \ X=1/2 cycle |
715 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
716 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
718 \ ------------------------------\
719 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
720 \ ------------------------------\
721 BIT.B #RC5,&IR_IN \ C_flag = IR bit
722 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
723 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
724 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
725 SUB #1,W \ decrement count loop
726 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
727 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
728 0<> WHILE \ ----> out of loop ----+
729 \ RC5_compute_7/4_Time_out: \ |
730 ADD X,Y \ | out of bound = 7/4 period
731 \ RC5_WaitHalfCycleP1.2_IFG: \ |
733 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
734 0>= IF \ | if cycle time out of bound
735 BIC #$30,&TA0CTL \ | stop timer_A0
736 RETI \ | then quit to do nothing
738 \ ------------------------------\ |
739 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
741 MOV &TA0R,X \ | | get new RC5_period value
742 REPEAT \ ----> loop back --+ |
743 \ ------------------------------\ |
744 \ RC5_SampleEndOf: \ <---------------------+
745 \ ------------------------------\
746 BIC #$30,&TA0CTL \ stop timer_A0
747 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
748 \ ******************************\
749 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
750 \ ******************************\
751 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
752 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
753 XOR IP,X \ (new XOR old) Toggle bit (13)
754 BIT #BIT13,X \ X(13) = New_RC5_command
755 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
757 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
758 \ ******************************\
759 \ RC5_ComputeNewRC5word \
760 \ ******************************\
762 MOV &BASE,2(PSP) \ save variable BASE before use
763 MOV TOS,0(PSP) \ save TOS before use
764 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
765 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
766 \ ******************************\
768 \ ******************************\
769 BIT #$4000,IP \ test /C6 bit in IP
770 0= IF BIS #$40,TOS \ set C6 bit in S
771 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
772 \ ******************************\
773 \ RC5_CommandByteIsDone \ RC5_code --
774 \ ******************************\
776 \ ------------------------------\
777 \ Display IR_RC5 code \
778 \ ------------------------------\
779 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
780 \ ------------------------------\
781 LO2HI \ switch from assembler to FORTH
782 ['] LCD_CLEAR IS CR \ redirects CR
783 ['] LCD_WrC IS EMIT \ redirects EMIT
784 $10 BASE ! \ change BASE to hexadecimal
785 CR ." $" 2 U.R \ print IR_RC5 code
786 ['] (CR) IS CR \ restore CR
787 ['] (EMIT) IS EMIT \ restore EMIT
788 HI2LO \ switch from FORTH to assembler
789 \ ------------------------------\
790 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
791 \ ------------------------------\
792 MOV @PSP+,&BASE \ restore variable BASE
793 RETI \ CPU is ON, GIE is OFF
798 \ ------------------------------\
799 \ TB0CTL = %0000 0010 1001 0100\$3C0
800 \ - - \CNTL Counter lentgh \ 00 = 16 bits
801 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
802 \ -- \ID input divider \ 10 = /4
803 \ -- \MC Mode Control \ 01 = up to TB0CCR0
804 \ - \TBCLR TimerB Clear
807 \ --------------------------------\\
808 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
809 \ -- \CM Capture Mode
814 \ --- \OUTMOD \ 011 = set/reset
820 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
822 \ ------------------------------\
823 \ set TimerB to make 50kHz PWM \
824 \ ------------------------------\
825 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
826 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
827 \ ------------------------------\
828 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
829 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
830 \ ------------------------------\
831 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
832 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
833 \ ------------------------------\
834 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
835 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
836 \ ------------------------------\
837 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
838 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
839 \ ------------------------------\
840 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
841 \ ------------------------------\
842 \ set TimerB to generate PWM for LCD_Vo
843 \ ------------------------------\
844 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
845 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
846 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
847 \ ------------------------------\
848 BIS.B #LCDVo,&LCDVo_DIR \
849 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
850 \ ------------------------------\
851 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
852 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
853 \ ------------------------------\
854 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
855 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
856 \ ------------------------------\
857 \ WDT interval init part \
858 \ ------------------------------\
859 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
860 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
861 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
862 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
863 \ ------------------------------\
865 \ ------------------------------\
866 BIS.B #RC5,&IR_IE \ enable RC5_Int
867 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
868 \ ------------------------------\
869 \ init interrupt vectors
870 \ ------------------------------\
871 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
872 MOV #RC5_INT,&IR_Vec \ init interrupt vector
873 \ ------------------------------\
874 \ define LPM mode for ACCEPT \
875 \ ------------------------------\
876 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
877 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
878 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
880 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
882 \ ------------------------------\
884 \ ------------------------------\
885 $03E8 20_US \ 1- wait 20 ms
886 $03 TOP_LCD \ 2- send DB5=DB4=1
887 $CD 20_US \ 3- wait 4,1 ms
888 $03 TOP_LCD \ 4- send again DB5=DB4=1
889 $5 20_US \ 5- wait 0,1 ms
890 $03 TOP_LCD \ 6- send again again DB5=DB4=1
891 $2 20_US \ wait 40 us = LCD cycle
892 $02 TOP_LCD \ 7- send DB5=1 DB4=0
893 $2 20_US \ wait 40 us = LCD cycle
894 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
895 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
896 LCD_Clear \ 10- "LCD_Clear"
897 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
898 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
899 LCD_Clear \ 10- "LCD_Clear"
900 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
901 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
903 ['] (CR) IS CR \ ' (CR) is CR
904 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
906 ." RC5toLCD is running. Type STOP to quit"
907 \ NOECHO \ uncomment to run this app without terminal connexion
908 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
909 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
913 : STOP \ stops multitasking, must to be used before downloading app
914 ['] (WARM) IS WARM \ remove START app from FORTH init process
915 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
924 CODE MAX \ n1 n2 -- n3 signed maximum
932 CODE MIN \ n1 n2 -- n3 signed minimum
940 : U.R \ u n -- display u unsigned in n width (n >= 2)
942 R> OVER - 0 MAX SPACES TYPE
946 CODE 20_US \ n -- n * 20 us
947 BEGIN \ 3 cycles loop + 6~
948 \ MOV #5,W \ 3 MCLK = 1 MHz
949 \ MOV #23,W \ 3 MCLK = 4 MHz
950 MOV #51,W \ 3 MCLK = 8 MHz
951 \ MOV #104,W \ 3 MCLK = 16 MHz
952 \ MOV #158,W \ 3 MCLK = 24 MHz
953 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
963 CODE TOP_LCD \ LCD Sample
964 \ \ if write : %xxxxWWWW --
965 \ \ if read : -- %0000RRRR
966 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
967 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
968 0= IF \ write LCD bits pattern
970 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
971 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
974 THEN \ read LCD bits pattern
977 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
978 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
984 CODE LCD_W \ byte -- write byte to LCD
986 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
987 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
988 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
989 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
990 COLON \ high level word starts here
991 TOP_LCD 2 20_US \ write high nibble first
996 CODE LCD_WrC \ char -- Write Char
997 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1002 CODE LCD_WrF \ func -- Write Fonction
1003 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1009 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1014 $02 LCD_WrF 100 20_us
1018 \ : LCD_Entry_set $04 OR LCD_WrF ;
1020 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1022 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1024 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1026 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1028 \ : LCD_Goto $80 OR LCD_WrF ;
1030 \ CODE LCD_R \ -- byte read byte from LCD
1031 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1032 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1033 \ COLON \ starts a FORTH word
1034 \ TOP_LCD 2 20_us \ -- %0000HHHH
1035 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1036 \ HI2LO \ switch from FORTH to assembler
1037 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1038 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1039 \ MOV @RSP+,IP \ restore IP saved by COLON
1044 \ CODE LCD_RdS \ -- status Read Status
1045 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1050 \ CODE LCD_RdC \ -- char Read Char
1051 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1056 \ -------------+------+------+------+------++---+---+---+---+---------+
1057 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1058 \ -------------+------+------+------+------++---+---+---+---+---------+
1059 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1060 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1061 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1062 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1063 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1064 \ -------------+------+------+------+------++---+---+---+---+---------+
1067 \ ******************************\
1068 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1069 \ ******************************\
1070 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1071 \ ------------------------------\
1072 \ define LPM mode for ACCEPT \
1073 \ ------------------------------\
1074 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1075 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1076 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1077 BIT.B #SW2,&SW2_IN \ test switch S2
1078 0= IF \ case of switch S2 pressed
1079 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1081 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1084 BIT.B #SW1,&SW1_IN \ test switch S1 input
1085 0= IF \ case of Switch S1 pressed
1086 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1088 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1092 RETI \ CPU is ON, GIE is OFF
1097 \ ------------------------------\
1098 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1099 \ ******************************\
1100 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1101 \ ******************************\
1102 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1103 \ \ SMclock = 8|16|24 MHz
1104 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1105 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1106 \ \ SR(9)=new Toggle bit memory (ADD on)
1107 \ ------------------------------\
1108 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1109 \ ------------------------------\
1110 \ define LPM mode for ACCEPT \
1111 \ ------------------------------\
1112 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1113 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1114 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1115 \ ------------------------------\
1116 \ RC5_FirstStartBitHalfCycle: \
1117 \ ------------------------------\
1118 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1119 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1120 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1121 MOV #1778,X \ RC5_Period in us
1122 MOV #14,W \ count of loop
1124 \ ------------------------------\
1125 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1126 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1127 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1128 \ RC5_Compute_3/4_Period: \ |
1129 RRUM #1,X \ X=1/2 cycle |
1133 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1134 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1136 \ ------------------------------\
1137 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1138 \ ------------------------------\
1139 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1140 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1141 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1142 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1143 SUB #1,W \ decrement count loop
1144 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1145 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1146 0<> WHILE \ ----> out of loop ----+
1147 \ RC5_compute_7/4_Time_out: \ |
1148 ADD X,Y \ | out of bound = 7/4 period
1149 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1151 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1152 0>= IF \ | if cycle time out of bound
1153 BIC #$30,&TA0CTL \ | stop timer_A0
1154 RETI \ | then quit to do nothing
1156 \ ------------------------------\ |
1157 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1159 MOV &TA0R,X \ | | get new RC5_period value
1160 REPEAT \ ----> loop back --+ |
1161 \ ------------------------------\ |
1162 \ RC5_SampleEndOf: \ <---------------------+
1163 \ ------------------------------\
1164 BIC #$30,&TA0CTL \ stop timer_A0
1165 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1166 \ ******************************\
1167 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1168 \ ******************************\
1169 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
1170 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
1171 XOR IP,X \ (new XOR old) Toggle bit (13)
1172 BIT #BIT13,X \ X(13) = New_RC5_command
1173 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
1175 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
1176 \ ******************************\
1177 \ RC5_ComputeNewRC5word \
1178 \ ******************************\
1180 MOV &BASE,2(PSP) \ save variable BASE before use
1181 MOV TOS,0(PSP) \ save TOS before use
1182 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
1183 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
1184 \ ******************************\
1185 \ RC5_ComputeC6bit \
1186 \ ******************************\
1187 BIT #$4000,IP \ test /C6 bit in IP
1188 0= IF BIS #$40,TOS \ set C6 bit in S
1189 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
1190 \ ******************************\
1191 \ RC5_CommandByteIsDone \ RC5_code --
1192 \ ******************************\
1194 \ ------------------------------\
1195 \ Display IR_RC5 code \
1196 \ ------------------------------\
1197 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
1198 \ ------------------------------\
1199 LO2HI \ switch from assembler to FORTH
1200 ['] LCD_CLEAR IS CR \ redirects CR
1201 ['] LCD_WrC IS EMIT \ redirects EMIT
1202 $10 BASE ! \ change BASE to hexadecimal
1203 CR ." $" 2 U.R \ print IR_RC5 code
1204 ['] (CR) IS CR \ restore CR
1205 ['] (EMIT) IS EMIT \ restore EMIT
1206 HI2LO \ switch from FORTH to assembler
1207 \ ------------------------------\
1208 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
1209 \ ------------------------------\
1210 MOV @PSP+,&BASE \ restore variable BASE
1211 RETI \ CPU is ON, GIE is OFF
1216 \ ------------------------------\
1217 \ TB0CTL = %0000 0010 1001 0100\$3C0
1218 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1219 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1220 \ -- \ID input divider \ 10 = /4
1221 \ -- \MC Mode Control \ 01 = up to TB0CCR0
1222 \ - \TBCLR TimerB Clear
1225 \ --------------------------------\\
1226 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1227 \ -- \CM Capture Mode
1232 \ --- \OUTMOD \ 011 = set/reset
1238 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
1240 \ ------------------------------\
1241 \ set TimerB to make 50kHz PWM \
1242 \ ------------------------------\
1243 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1244 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
1245 \ ------------------------------\
1246 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1247 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
1248 \ ------------------------------\
1249 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1250 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
1251 \ ------------------------------\
1252 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1253 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
1254 \ ------------------------------\
1255 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1256 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
1257 \ ------------------------------\
1258 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
1259 \ ------------------------------\
1260 \ set TimerB to generate PWM for LCD_Vo
1261 \ ------------------------------\
1262 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
1263 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
1264 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1265 \ ------------------------------\
1266 BIS.B #LCDVo,&LCDVo_DIR \
1267 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
1268 \ ------------------------------\
1269 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1270 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1271 \ ------------------------------\
1272 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1273 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1274 \ ------------------------------\
1275 \ WDT interval init part \
1276 \ ------------------------------\
1277 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
1278 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
1279 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
1280 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
1281 \ ------------------------------\
1283 \ ------------------------------\
1284 BIS.B #RC5,&IR_IE \ enable RC5_Int
1285 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1286 \ ------------------------------\
1287 \ init interrupt vectors
1288 \ ------------------------------\
1289 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
1290 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1291 \ ------------------------------\
1292 \ define LPM mode for ACCEPT \
1293 \ ------------------------------\
1294 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1295 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1296 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1298 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
1300 \ ------------------------------\
1302 \ ------------------------------\
1303 $03E8 20_US \ 1- wait 20 ms
1304 $03 TOP_LCD \ 2- send DB5=DB4=1
1305 $CD 20_US \ 3- wait 4,1 ms
1306 $03 TOP_LCD \ 4- send again DB5=DB4=1
1307 $5 20_US \ 5- wait 0,1 ms
1308 $03 TOP_LCD \ 6- send again again DB5=DB4=1
1309 $2 20_US \ wait 40 us = LCD cycle
1310 $02 TOP_LCD \ 7- send DB5=1 DB4=0
1311 $2 20_US \ wait 40 us = LCD cycle
1312 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1313 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1314 LCD_Clear \ 10- "LCD_Clear"
1315 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1316 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1317 LCD_Clear \ 10- "LCD_Clear"
1318 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1319 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1321 ['] (CR) IS CR \ ' (CR) is CR
1322 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
1324 ." RC5toLCD is running. Type STOP to quit"
1325 \ NOECHO \ uncomment to run this app without terminal connexion
1326 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
1327 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
1331 : STOP \ stops multitasking, must to be used before downloading app
1332 ['] (WARM) IS WARM \ remove START app from FORTH init process
1333 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
1342 CODE MAX \ n1 n2 -- n3 signed maximum
1343 CMP @PSP,TOS \ n2-n1
1344 S< ?GOTO FW1 \ n2<n1
1350 CODE MIN \ n1 n2 -- n3 signed minimum
1351 CMP @PSP,TOS \ n2-n1
1352 S< ?GOTO BW1 \ n2<n1
1358 : U.R \ u n -- display u unsigned in n width (n >= 2)
1360 R> OVER - 0 MAX SPACES TYPE
1364 CODE 20_US \ n -- n * 20 us
1365 BEGIN \ 3 cycles loop + 6~
1366 \ MOV #5,W \ 3 MCLK = 1 MHz
1367 \ MOV #23,W \ 3 MCLK = 4 MHz
1368 MOV #51,W \ 3 MCLK = 8 MHz
1369 \ MOV #104,W \ 3 MCLK = 16 MHz
1370 \ MOV #158,W \ 3 MCLK = 24 MHz
1371 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
1381 CODE TOP_LCD \ LCD Sample
1382 \ \ if write : %xxxxWWWW --
1383 \ \ if read : -- %0000RRRR
1384 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1385 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1386 0= IF \ write LCD bits pattern
1388 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1389 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1392 THEN \ read LCD bits pattern
1395 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1396 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1402 CODE LCD_W \ byte -- write byte to LCD
1404 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1405 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1406 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1407 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1408 COLON \ high level word starts here
1409 TOP_LCD 2 20_US \ write high nibble first
1414 CODE LCD_WrC \ char -- Write Char
1415 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1420 CODE LCD_WrF \ func -- Write Fonction
1421 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1427 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1432 $02 LCD_WrF 100 20_us
1436 \ : LCD_Entry_set $04 OR LCD_WrF ;
1438 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1440 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1442 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1444 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1446 \ : LCD_Goto $80 OR LCD_WrF ;
1448 \ CODE LCD_R \ -- byte read byte from LCD
1449 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1450 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1451 \ COLON \ starts a FORTH word
1452 \ TOP_LCD 2 20_us \ -- %0000HHHH
1453 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1454 \ HI2LO \ switch from FORTH to assembler
1455 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1456 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1457 \ MOV @RSP+,IP \ restore IP saved by COLON
1462 \ CODE LCD_RdS \ -- status Read Status
1463 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1468 \ CODE LCD_RdC \ -- char Read Char
1469 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1474 \ -------------+------+------+------+------++---+---+---+---+---------+
1475 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1476 \ -------------+------+------+------+------++---+---+---+---+---------+
1477 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1478 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1479 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1480 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1481 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1482 \ -------------+------+------+------+------++---+---+---+---+---------+
1485 \ ******************************\
1486 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1487 \ ******************************\
1488 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1489 \ ------------------------------\
1490 \ define LPM mode for ACCEPT \
1491 \ ------------------------------\
1492 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1493 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1494 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1495 BIT.B #SW2,&SW2_IN \ test switch S2
1496 0= IF \ case of switch S2 pressed
1497 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1499 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1502 BIT.B #SW1,&SW1_IN \ test switch S1 input
1503 0= IF \ case of Switch S1 pressed
1504 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1506 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1510 RETI \ CPU is ON, GIE is OFF
1515 \ ------------------------------\
1516 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1517 \ ******************************\
1518 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1519 \ ******************************\
1520 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1521 \ \ SMclock = 8|16|24 MHz
1522 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1523 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1524 \ \ SR(9)=new Toggle bit memory (ADD on)
1525 \ ------------------------------\
1526 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1527 \ ------------------------------\
1528 \ define LPM mode for ACCEPT \
1529 \ ------------------------------\
1530 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1531 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1532 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1533 \ ------------------------------\
1534 \ RC5_FirstStartBitHalfCycle: \
1535 \ ------------------------------\
1536 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1537 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1538 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1539 MOV #1778,X \ RC5_Period in us
1540 MOV #14,W \ count of loop
1542 \ ------------------------------\
1543 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1544 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1545 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1546 \ RC5_Compute_3/4_Period: \ |
1547 RRUM #1,X \ X=1/2 cycle |
1551 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1552 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1554 \ ------------------------------\
1555 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1556 \ ------------------------------\
1557 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1558 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1559 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1560 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1561 SUB #1,W \ decrement count loop
1562 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1563 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1564 0<> WHILE \ ----> out of loop ----+
1565 \ RC5_compute_7/4_Time_out: \ |
1566 ADD X,Y \ | out of bound = 7/4 period
1567 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1569 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1570 0>= IF \ | if cycle time out of bound
1571 BIC #$30,&TA0CTL \ | stop timer_A0
1572 RETI \ | then quit to do nothing
1574 \ ------------------------------\ |
1575 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1577 MOV &TA0R,X \ | | get new RC5_period value
1578 REPEAT \ ----> loop back --+ |
1579 \ ------------------------------\ |
1580 \ RC5_SampleEndOf: \ <---------------------+
1581 \ ------------------------------\
1582 BIC #$30,&TA0CTL \ stop timer_A0
1583 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
1584 \ ******************************\
1585 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1586 \ ******************************\
1587 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
1588 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
1589 XOR IP,X \ (new XOR old) Toggle bit (13)
1590 BIT #BIT13,X \ X(13) = New_RC5_command
1591 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
1593 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
1594 \ ******************************\
1595 \ RC5_ComputeNewRC5word \
1596 \ ******************************\
1598 MOV &BASE,2(PSP) \ save variable BASE before use
1599 MOV TOS,0(PSP) \ save TOS before use
1600 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
1601 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
1602 \ ******************************\
1603 \ RC5_ComputeC6bit \
1604 \ ******************************\
1605 BIT #$4000,IP \ test /C6 bit in IP
1606 0= IF BIS #$40,TOS \ set C6 bit in S
1607 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
1608 \ ******************************\
1609 \ RC5_CommandByteIsDone \ RC5_code --
1610 \ ******************************\
1612 \ ------------------------------\
1613 \ Display IR_RC5 code \
1614 \ ------------------------------\
1615 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
1616 \ ------------------------------\
1617 LO2HI \ switch from assembler to FORTH
1618 ['] LCD_CLEAR IS CR \ redirects CR
1619 ['] LCD_WrC IS EMIT \ redirects EMIT
1620 $10 BASE ! \ change BASE to hexadecimal
1621 CR ." $" 2 U.R \ print IR_RC5 code
1622 ['] (CR) IS CR \ restore CR
1623 ['] (EMIT) IS EMIT \ restore EMIT
1624 HI2LO \ switch from FORTH to assembler
1625 \ ------------------------------\
1626 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
1627 \ ------------------------------\
1628 MOV @PSP+,&BASE \ restore variable BASE
1629 RETI \ CPU is ON, GIE is OFF
1634 \ ------------------------------\
1635 \ TB0CTL = %0000 0010 1001 0100\$3C0
1636 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1637 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1638 \ -- \ID input divider \ 10 = /4
1639 \ -- \MC Mode Control \ 01 = up to TB0CCR0
1640 \ - \TBCLR TimerB Clear
1643 \ --------------------------------\\
1644 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1645 \ -- \CM Capture Mode
1650 \ --- \OUTMOD \ 011 = set/reset
1656 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
1658 \ ------------------------------\
1659 \ set TimerB to make 50kHz PWM \
1660 \ ------------------------------\
1661 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1662 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
1663 \ ------------------------------\
1664 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
1665 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
1666 \ ------------------------------\
1667 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1668 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
1669 \ ------------------------------\
1670 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1671 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
1672 \ ------------------------------\
1673 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
1674 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
1675 \ ------------------------------\
1676 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
1677 \ ------------------------------\
1678 \ set TimerB to generate PWM for LCD_Vo
1679 \ ------------------------------\
1680 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
1681 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
1682 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1683 \ ------------------------------\
1684 BIS.B #LCDVo,&LCDVo_DIR \
1685 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
1686 \ ------------------------------\
1687 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1688 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1689 \ ------------------------------\
1690 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1691 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1692 \ ------------------------------\
1693 \ WDT interval init part \
1694 \ ------------------------------\
1695 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
1696 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
1697 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
1698 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
1699 \ ------------------------------\
1701 \ ------------------------------\
1702 BIS.B #RC5,&IR_IE \ enable RC5_Int
1703 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1704 \ ------------------------------\
1705 \ init interrupt vectors
1706 \ ------------------------------\
1707 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
1708 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1709 \ ------------------------------\
1710 \ define LPM mode for ACCEPT \
1711 \ ------------------------------\
1712 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1713 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1714 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1716 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
1718 \ ------------------------------\
1720 \ ------------------------------\
1721 $03E8 20_US \ 1- wait 20 ms
1722 $03 TOP_LCD \ 2- send DB5=DB4=1
1723 $CD 20_US \ 3- wait 4,1 ms
1724 $03 TOP_LCD \ 4- send again DB5=DB4=1
1725 $5 20_US \ 5- wait 0,1 ms
1726 $03 TOP_LCD \ 6- send again again DB5=DB4=1
1727 $2 20_US \ wait 40 us = LCD cycle
1728 $02 TOP_LCD \ 7- send DB5=1 DB4=0
1729 $2 20_US \ wait 40 us = LCD cycle
1730 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1731 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1732 LCD_Clear \ 10- "LCD_Clear"
1733 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1734 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1735 LCD_Clear \ 10- "LCD_Clear"
1736 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1737 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1739 ['] (CR) IS CR \ ' (CR) is CR
1740 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
1742 ." RC5toLCD is running. Type STOP to quit"
1743 \ NOECHO \ uncomment to run this app without terminal connexion
1744 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
1745 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
1749 : STOP \ stops multitasking, must to be used before downloading app
1750 ['] (WARM) IS WARM \ remove START app from FORTH init process
1751 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
1760 CODE MAX \ n1 n2 -- n3 signed maximum
1761 CMP @PSP,TOS \ n2-n1
1762 S< ?GOTO FW1 \ n2<n1
1768 CODE MIN \ n1 n2 -- n3 signed minimum
1769 CMP @PSP,TOS \ n2-n1
1770 S< ?GOTO BW1 \ n2<n1
1776 : U.R \ u n -- display u unsigned in n width (n >= 2)
1778 R> OVER - 0 MAX SPACES TYPE
1782 CODE 20_US \ n -- n * 20 us
1783 BEGIN \ 3 cycles loop + 6~
1784 \ MOV #5,W \ 3 MCLK = 1 MHz
1785 \ MOV #23,W \ 3 MCLK = 4 MHz
1786 MOV #51,W \ 3 MCLK = 8 MHz
1787 \ MOV #104,W \ 3 MCLK = 16 MHz
1788 \ MOV #158,W \ 3 MCLK = 24 MHz
1789 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
1799 CODE TOP_LCD \ LCD Sample
1800 \ \ if write : %xxxxWWWW --
1801 \ \ if read : -- %0000RRRR
1802 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1803 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1804 0= IF \ write LCD bits pattern
1806 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1807 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1810 THEN \ read LCD bits pattern
1813 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1814 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1820 CODE LCD_W \ byte -- write byte to LCD
1822 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
1823 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
1824 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1825 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1826 COLON \ high level word starts here
1827 TOP_LCD 2 20_US \ write high nibble first
1832 CODE LCD_WrC \ char -- Write Char
1833 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1838 CODE LCD_WrF \ func -- Write Fonction
1839 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1845 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
1850 $02 LCD_WrF 100 20_us
1854 \ : LCD_Entry_set $04 OR LCD_WrF ;
1856 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
1858 \ : LCD_Display_Shift $10 OR LCD_WrF ;
1860 \ : LCD_Fn_Set $20 OR LCD_WrF ;
1862 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
1864 \ : LCD_Goto $80 OR LCD_WrF ;
1866 \ CODE LCD_R \ -- byte read byte from LCD
1867 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1868 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1869 \ COLON \ starts a FORTH word
1870 \ TOP_LCD 2 20_us \ -- %0000HHHH
1871 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
1872 \ HI2LO \ switch from FORTH to assembler
1873 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
1874 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
1875 \ MOV @RSP+,IP \ restore IP saved by COLON
1880 \ CODE LCD_RdS \ -- status Read Status
1881 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1886 \ CODE LCD_RdC \ -- char Read Char
1887 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1892 \ -------------+------+------+------+------++---+---+---+---+---------+
1893 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
1894 \ -------------+------+------+------+------++---+---+---+---+---------+
1895 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
1896 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
1897 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
1898 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
1899 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
1900 \ -------------+------+------+------+------++---+---+---+---+---------+
1903 \ ******************************\
1904 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1905 \ ******************************\
1906 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
1907 \ ------------------------------\
1908 \ define LPM mode for ACCEPT \
1909 \ ------------------------------\
1910 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1911 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1912 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1913 BIT.B #SW2,&SW2_IN \ test switch S2
1914 0= IF \ case of switch S2 pressed
1915 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
1917 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
1920 BIT.B #SW1,&SW1_IN \ test switch S1 input
1921 0= IF \ case of Switch S1 pressed
1922 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
1924 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
1928 RETI \ CPU is ON, GIE is OFF
1933 \ ------------------------------\
1934 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1935 \ ******************************\
1936 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1937 \ ******************************\
1938 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1939 \ \ SMclock = 8|16|24 MHz
1940 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
1941 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
1942 \ \ SR(9)=new Toggle bit memory (ADD on)
1943 \ ------------------------------\
1944 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
1945 \ ------------------------------\
1946 \ define LPM mode for ACCEPT \
1947 \ ------------------------------\
1948 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1949 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1950 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1951 \ ------------------------------\
1952 \ RC5_FirstStartBitHalfCycle: \
1953 \ ------------------------------\
1954 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
1955 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
1956 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
1957 MOV #1778,X \ RC5_Period in us
1958 MOV #14,W \ count of loop
1960 \ ------------------------------\
1961 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
1962 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
1963 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
1964 \ RC5_Compute_3/4_Period: \ |
1965 RRUM #1,X \ X=1/2 cycle |
1969 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
1970 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
1972 \ ------------------------------\
1973 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
1974 \ ------------------------------\
1975 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1976 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
1977 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1978 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1979 SUB #1,W \ decrement count loop
1980 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
1981 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1982 0<> WHILE \ ----> out of loop ----+
1983 \ RC5_compute_7/4_Time_out: \ |
1984 ADD X,Y \ | out of bound = 7/4 period
1985 \ RC5_WaitHalfCycleP1.2_IFG: \ |
1987 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
1988 0>= IF \ | if cycle time out of bound
1989 BIC #$30,&TA0CTL \ | stop timer_A0
1990 RETI \ | then quit to do nothing
1992 \ ------------------------------\ |
1993 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
1995 MOV &TA0R,X \ | | get new RC5_period value
1996 REPEAT \ ----> loop back --+ |
1997 \ ------------------------------\ |
1998 \ RC5_SampleEndOf: \ <---------------------+
1999 \ ------------------------------\
2000 BIC #$30,&TA0CTL \ stop timer_A0
2001 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2002 \ ******************************\
2003 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2004 \ ******************************\
2005 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
2006 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2007 XOR IP,X \ (new XOR old) Toggle bit (13)
2008 BIT #BIT13,X \ X(13) = New_RC5_command
2009 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2011 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2012 \ ******************************\
2013 \ RC5_ComputeNewRC5word \
2014 \ ******************************\
2016 MOV &BASE,2(PSP) \ save variable BASE before use
2017 MOV TOS,0(PSP) \ save TOS before use
2018 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2019 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2020 \ ******************************\
2021 \ RC5_ComputeC6bit \
2022 \ ******************************\
2023 BIT #$4000,IP \ test /C6 bit in IP
2024 0= IF BIS #$40,TOS \ set C6 bit in S
2025 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2026 \ ******************************\
2027 \ RC5_CommandByteIsDone \ RC5_code --
2028 \ ******************************\
2030 \ ------------------------------\
2031 \ Display IR_RC5 code \
2032 \ ------------------------------\
2033 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2034 \ ------------------------------\
2035 LO2HI \ switch from assembler to FORTH
2036 ['] LCD_CLEAR IS CR \ redirects CR
2037 ['] LCD_WrC IS EMIT \ redirects EMIT
2038 $10 BASE ! \ change BASE to hexadecimal
2039 CR ." $" 2 U.R \ print IR_RC5 code
2040 ['] (CR) IS CR \ restore CR
2041 ['] (EMIT) IS EMIT \ restore EMIT
2042 HI2LO \ switch from FORTH to assembler
2043 \ ------------------------------\
2044 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2045 \ ------------------------------\
2046 MOV @PSP+,&BASE \ restore variable BASE
2047 RETI \ CPU is ON, GIE is OFF
2052 \ ------------------------------\
2053 \ TB0CTL = %0000 0010 1001 0100\$3C0
2054 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2055 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2056 \ -- \ID input divider \ 10 = /4
2057 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2058 \ - \TBCLR TimerB Clear
2061 \ --------------------------------\\
2062 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2063 \ -- \CM Capture Mode
2068 \ --- \OUTMOD \ 011 = set/reset
2074 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2076 \ ------------------------------\
2077 \ set TimerB to make 50kHz PWM \
2078 \ ------------------------------\
2079 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2080 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2081 \ ------------------------------\
2082 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2083 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2084 \ ------------------------------\
2085 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2086 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2087 \ ------------------------------\
2088 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2089 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2090 \ ------------------------------\
2091 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2092 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2093 \ ------------------------------\
2094 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2095 \ ------------------------------\
2096 \ set TimerB to generate PWM for LCD_Vo
2097 \ ------------------------------\
2098 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2099 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2100 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2101 \ ------------------------------\
2102 BIS.B #LCDVo,&LCDVo_DIR \
2103 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2104 \ ------------------------------\
2105 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2106 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2107 \ ------------------------------\
2108 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2109 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2110 \ ------------------------------\
2111 \ WDT interval init part \
2112 \ ------------------------------\
2113 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2114 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2115 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2116 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2117 \ ------------------------------\
2119 \ ------------------------------\
2120 BIS.B #RC5,&IR_IE \ enable RC5_Int
2121 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2122 \ ------------------------------\
2123 \ init interrupt vectors
2124 \ ------------------------------\
2125 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2126 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2127 \ ------------------------------\
2128 \ define LPM mode for ACCEPT \
2129 \ ------------------------------\
2130 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2131 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2132 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2134 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2136 \ ------------------------------\
2138 \ ------------------------------\
2139 $03E8 20_US \ 1- wait 20 ms
2140 $03 TOP_LCD \ 2- send DB5=DB4=1
2141 $CD 20_US \ 3- wait 4,1 ms
2142 $03 TOP_LCD \ 4- send again DB5=DB4=1
2143 $5 20_US \ 5- wait 0,1 ms
2144 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2145 $2 20_US \ wait 40 us = LCD cycle
2146 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2147 $2 20_US \ wait 40 us = LCD cycle
2148 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2149 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2150 LCD_Clear \ 10- "LCD_Clear"
2151 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2152 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2153 LCD_Clear \ 10- "LCD_Clear"
2154 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2155 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2157 ['] (CR) IS CR \ ' (CR) is CR
2158 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2160 ." RC5toLCD is running. Type STOP to quit"
2161 \ NOECHO \ uncomment to run this app without terminal connexion
2162 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2163 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2167 : STOP \ stops multitasking, must to be used before downloading app
2168 ['] (WARM) IS WARM \ remove START app from FORTH init process
2169 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
2178 CODE MAX \ n1 n2 -- n3 signed maximum
2179 CMP @PSP,TOS \ n2-n1
2180 S< ?GOTO FW1 \ n2<n1
2186 CODE MIN \ n1 n2 -- n3 signed minimum
2187 CMP @PSP,TOS \ n2-n1
2188 S< ?GOTO BW1 \ n2<n1
2194 : U.R \ u n -- display u unsigned in n width (n >= 2)
2196 R> OVER - 0 MAX SPACES TYPE
2200 CODE 20_US \ n -- n * 20 us
2201 BEGIN \ 3 cycles loop + 6~
2202 \ MOV #5,W \ 3 MCLK = 1 MHz
2203 \ MOV #23,W \ 3 MCLK = 4 MHz
2204 MOV #51,W \ 3 MCLK = 8 MHz
2205 \ MOV #104,W \ 3 MCLK = 16 MHz
2206 \ MOV #158,W \ 3 MCLK = 24 MHz
2207 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
2217 CODE TOP_LCD \ LCD Sample
2218 \ \ if write : %xxxxWWWW --
2219 \ \ if read : -- %0000RRRR
2220 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2221 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2222 0= IF \ write LCD bits pattern
2224 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2225 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2228 THEN \ read LCD bits pattern
2231 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2232 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2238 CODE LCD_W \ byte -- write byte to LCD
2240 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2241 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2242 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2243 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2244 COLON \ high level word starts here
2245 TOP_LCD 2 20_US \ write high nibble first
2250 CODE LCD_WrC \ char -- Write Char
2251 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2256 CODE LCD_WrF \ func -- Write Fonction
2257 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2263 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
2268 $02 LCD_WrF 100 20_us
2272 \ : LCD_Entry_set $04 OR LCD_WrF ;
2274 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
2276 \ : LCD_Display_Shift $10 OR LCD_WrF ;
2278 \ : LCD_Fn_Set $20 OR LCD_WrF ;
2280 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
2282 \ : LCD_Goto $80 OR LCD_WrF ;
2284 \ CODE LCD_R \ -- byte read byte from LCD
2285 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2286 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2287 \ COLON \ starts a FORTH word
2288 \ TOP_LCD 2 20_us \ -- %0000HHHH
2289 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2290 \ HI2LO \ switch from FORTH to assembler
2291 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2292 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2293 \ MOV @RSP+,IP \ restore IP saved by COLON
2298 \ CODE LCD_RdS \ -- status Read Status
2299 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2304 \ CODE LCD_RdC \ -- char Read Char
2305 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2310 \ -------------+------+------+------+------++---+---+---+---+---------+
2311 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
2312 \ -------------+------+------+------+------++---+---+---+---+---------+
2313 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
2314 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
2315 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
2316 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
2317 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
2318 \ -------------+------+------+------+------++---+---+---+---+---------+
2321 \ ******************************\
2322 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2323 \ ******************************\
2324 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
2325 \ ------------------------------\
2326 \ define LPM mode for ACCEPT \
2327 \ ------------------------------\
2328 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2329 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2330 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2331 BIT.B #SW2,&SW2_IN \ test switch S2
2332 0= IF \ case of switch S2 pressed
2333 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
2335 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
2338 BIT.B #SW1,&SW1_IN \ test switch S1 input
2339 0= IF \ case of Switch S1 pressed
2340 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
2342 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
2346 RETI \ CPU is ON, GIE is OFF
2351 \ ------------------------------\
2352 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2353 \ ******************************\
2354 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2355 \ ******************************\
2356 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2357 \ \ SMclock = 8|16|24 MHz
2358 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
2359 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
2360 \ \ SR(9)=new Toggle bit memory (ADD on)
2361 \ ------------------------------\
2362 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
2363 \ ------------------------------\
2364 \ define LPM mode for ACCEPT \
2365 \ ------------------------------\
2366 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2367 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2368 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2369 \ ------------------------------\
2370 \ RC5_FirstStartBitHalfCycle: \
2371 \ ------------------------------\
2372 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
2373 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
2374 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
2375 MOV #1778,X \ RC5_Period in us
2376 MOV #14,W \ count of loop
2378 \ ------------------------------\
2379 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
2380 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
2381 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
2382 \ RC5_Compute_3/4_Period: \ |
2383 RRUM #1,X \ X=1/2 cycle |
2387 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
2388 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
2390 \ ------------------------------\
2391 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
2392 \ ------------------------------\
2393 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2394 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
2395 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2396 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2397 SUB #1,W \ decrement count loop
2398 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
2399 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2400 0<> WHILE \ ----> out of loop ----+
2401 \ RC5_compute_7/4_Time_out: \ |
2402 ADD X,Y \ | out of bound = 7/4 period
2403 \ RC5_WaitHalfCycleP1.2_IFG: \ |
2405 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
2406 0>= IF \ | if cycle time out of bound
2407 BIC #$30,&TA0CTL \ | stop timer_A0
2408 RETI \ | then quit to do nothing
2410 \ ------------------------------\ |
2411 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
2413 MOV &TA0R,X \ | | get new RC5_period value
2414 REPEAT \ ----> loop back --+ |
2415 \ ------------------------------\ |
2416 \ RC5_SampleEndOf: \ <---------------------+
2417 \ ------------------------------\
2418 BIC #$30,&TA0CTL \ stop timer_A0
2419 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2420 \ ******************************\
2421 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2422 \ ******************************\
2423 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
2424 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2425 XOR IP,X \ (new XOR old) Toggle bit (13)
2426 BIT #BIT13,X \ X(13) = New_RC5_command
2427 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2429 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2430 \ ******************************\
2431 \ RC5_ComputeNewRC5word \
2432 \ ******************************\
2434 MOV &BASE,2(PSP) \ save variable BASE before use
2435 MOV TOS,0(PSP) \ save TOS before use
2436 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2437 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2438 \ ******************************\
2439 \ RC5_ComputeC6bit \
2440 \ ******************************\
2441 BIT #$4000,IP \ test /C6 bit in IP
2442 0= IF BIS #$40,TOS \ set C6 bit in S
2443 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2444 \ ******************************\
2445 \ RC5_CommandByteIsDone \ RC5_code --
2446 \ ******************************\
2448 \ ------------------------------\
2449 \ Display IR_RC5 code \
2450 \ ------------------------------\
2451 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2452 \ ------------------------------\
2453 LO2HI \ switch from assembler to FORTH
2454 ['] LCD_CLEAR IS CR \ redirects CR
2455 ['] LCD_WrC IS EMIT \ redirects EMIT
2456 $10 BASE ! \ change BASE to hexadecimal
2457 CR ." $" 2 U.R \ print IR_RC5 code
2458 ['] (CR) IS CR \ restore CR
2459 ['] (EMIT) IS EMIT \ restore EMIT
2460 HI2LO \ switch from FORTH to assembler
2461 \ ------------------------------\
2462 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2463 \ ------------------------------\
2464 MOV @PSP+,&BASE \ restore variable BASE
2465 RETI \ CPU is ON, GIE is OFF
2470 \ ------------------------------\
2471 \ TB0CTL = %0000 0010 1001 0100\$3C0
2472 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2473 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2474 \ -- \ID input divider \ 10 = /4
2475 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2476 \ - \TBCLR TimerB Clear
2479 \ --------------------------------\\
2480 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2481 \ -- \CM Capture Mode
2486 \ --- \OUTMOD \ 011 = set/reset
2492 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2494 \ ------------------------------\
2495 \ set TimerB to make 50kHz PWM \
2496 \ ------------------------------\
2497 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2498 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2499 \ ------------------------------\
2500 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2501 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2502 \ ------------------------------\
2503 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2504 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2505 \ ------------------------------\
2506 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2507 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2508 \ ------------------------------\
2509 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2510 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2511 \ ------------------------------\
2512 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2513 \ ------------------------------\
2514 \ set TimerB to generate PWM for LCD_Vo
2515 \ ------------------------------\
2516 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2517 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2518 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2519 \ ------------------------------\
2520 BIS.B #LCDVo,&LCDVo_DIR \
2521 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2522 \ ------------------------------\
2523 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2524 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2525 \ ------------------------------\
2526 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2527 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2528 \ ------------------------------\
2529 \ WDT interval init part \
2530 \ ------------------------------\
2531 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2532 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2533 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2534 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2535 \ ------------------------------\
2537 \ ------------------------------\
2538 BIS.B #RC5,&IR_IE \ enable RC5_Int
2539 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2540 \ ------------------------------\
2541 \ init interrupt vectors
2542 \ ------------------------------\
2543 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2544 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2545 \ ------------------------------\
2546 \ define LPM mode for ACCEPT \
2547 \ ------------------------------\
2548 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2549 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2550 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2552 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2554 \ ------------------------------\
2556 \ ------------------------------\
2557 $03E8 20_US \ 1- wait 20 ms
2558 $03 TOP_LCD \ 2- send DB5=DB4=1
2559 $CD 20_US \ 3- wait 4,1 ms
2560 $03 TOP_LCD \ 4- send again DB5=DB4=1
2561 $5 20_US \ 5- wait 0,1 ms
2562 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2563 $2 20_US \ wait 40 us = LCD cycle
2564 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2565 $2 20_US \ wait 40 us = LCD cycle
2566 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2567 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2568 LCD_Clear \ 10- "LCD_Clear"
2569 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2570 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2571 LCD_Clear \ 10- "LCD_Clear"
2572 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2573 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2575 ['] (CR) IS CR \ ' (CR) is CR
2576 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2578 ." RC5toLCD is running. Type STOP to quit"
2579 \ NOECHO \ uncomment to run this app without terminal connexion
2580 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2581 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
2585 : STOP \ stops multitasking, must to be used before downloading app
2586 ['] (WARM) IS WARM \ remove START app from FORTH init process
2587 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
2596 CODE MAX \ n1 n2 -- n3 signed maximum
2597 CMP @PSP,TOS \ n2-n1
2598 S< ?GOTO FW1 \ n2<n1
2604 CODE MIN \ n1 n2 -- n3 signed minimum
2605 CMP @PSP,TOS \ n2-n1
2606 S< ?GOTO BW1 \ n2<n1
2612 : U.R \ u n -- display u unsigned in n width (n >= 2)
2614 R> OVER - 0 MAX SPACES TYPE
2618 CODE 20_US \ n -- n * 20 us
2619 BEGIN \ 3 cycles loop + 6~
2620 \ MOV #5,W \ 3 MCLK = 1 MHz
2621 \ MOV #23,W \ 3 MCLK = 4 MHz
2622 MOV #51,W \ 3 MCLK = 8 MHz
2623 \ MOV #104,W \ 3 MCLK = 16 MHz
2624 \ MOV #158,W \ 3 MCLK = 24 MHz
2625 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
2635 CODE TOP_LCD \ LCD Sample
2636 \ \ if write : %xxxxWWWW --
2637 \ \ if read : -- %0000RRRR
2638 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2639 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2640 0= IF \ write LCD bits pattern
2642 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2643 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2646 THEN \ read LCD bits pattern
2649 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2650 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2656 CODE LCD_W \ byte -- write byte to LCD
2658 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
2659 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
2660 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2661 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2662 COLON \ high level word starts here
2663 TOP_LCD 2 20_US \ write high nibble first
2668 CODE LCD_WrC \ char -- Write Char
2669 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2674 CODE LCD_WrF \ func -- Write Fonction
2675 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2681 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
2686 $02 LCD_WrF 100 20_us
2690 \ : LCD_Entry_set $04 OR LCD_WrF ;
2692 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
2694 \ : LCD_Display_Shift $10 OR LCD_WrF ;
2696 \ : LCD_Fn_Set $20 OR LCD_WrF ;
2698 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
2700 \ : LCD_Goto $80 OR LCD_WrF ;
2702 \ CODE LCD_R \ -- byte read byte from LCD
2703 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2704 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2705 \ COLON \ starts a FORTH word
2706 \ TOP_LCD 2 20_us \ -- %0000HHHH
2707 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
2708 \ HI2LO \ switch from FORTH to assembler
2709 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
2710 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
2711 \ MOV @RSP+,IP \ restore IP saved by COLON
2716 \ CODE LCD_RdS \ -- status Read Status
2717 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2722 \ CODE LCD_RdC \ -- char Read Char
2723 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2728 \ -------------+------+------+------+------++---+---+---+---+---------+
2729 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
2730 \ -------------+------+------+------+------++---+---+---+---+---------+
2731 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
2732 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
2733 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
2734 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
2735 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
2736 \ -------------+------+------+------+------++---+---+---+---+---------+
2739 \ ******************************\
2740 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2741 \ ******************************\
2742 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
2743 \ ------------------------------\
2744 \ define LPM mode for ACCEPT \
2745 \ ------------------------------\
2746 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2747 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2748 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2749 BIT.B #SW2,&SW2_IN \ test switch S2
2750 0= IF \ case of switch S2 pressed
2751 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
2753 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
2756 BIT.B #SW1,&SW1_IN \ test switch S1 input
2757 0= IF \ case of Switch S1 pressed
2758 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
2760 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
2764 RETI \ CPU is ON, GIE is OFF
2769 \ ------------------------------\
2770 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2771 \ ******************************\
2772 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2773 \ ******************************\
2774 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2775 \ \ SMclock = 8|16|24 MHz
2776 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
2777 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
2778 \ \ SR(9)=new Toggle bit memory (ADD on)
2779 \ ------------------------------\
2780 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
2781 \ ------------------------------\
2782 \ define LPM mode for ACCEPT \
2783 \ ------------------------------\
2784 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2785 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2786 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2787 \ ------------------------------\
2788 \ RC5_FirstStartBitHalfCycle: \
2789 \ ------------------------------\
2790 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
2791 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
2792 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
2793 MOV #1778,X \ RC5_Period in us
2794 MOV #14,W \ count of loop
2796 \ ------------------------------\
2797 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
2798 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
2799 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
2800 \ RC5_Compute_3/4_Period: \ |
2801 RRUM #1,X \ X=1/2 cycle |
2805 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
2806 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
2808 \ ------------------------------\
2809 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
2810 \ ------------------------------\
2811 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2812 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
2813 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2814 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2815 SUB #1,W \ decrement count loop
2816 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
2817 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2818 0<> WHILE \ ----> out of loop ----+
2819 \ RC5_compute_7/4_Time_out: \ |
2820 ADD X,Y \ | out of bound = 7/4 period
2821 \ RC5_WaitHalfCycleP1.2_IFG: \ |
2823 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
2824 0>= IF \ | if cycle time out of bound
2825 BIC #$30,&TA0CTL \ | stop timer_A0
2826 RETI \ | then quit to do nothing
2828 \ ------------------------------\ |
2829 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
2831 MOV &TA0R,X \ | | get new RC5_period value
2832 REPEAT \ ----> loop back --+ |
2833 \ ------------------------------\ |
2834 \ RC5_SampleEndOf: \ <---------------------+
2835 \ ------------------------------\
2836 BIC #$30,&TA0CTL \ stop timer_A0
2837 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
2838 \ ******************************\
2839 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2840 \ ******************************\
2841 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
2842 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
2843 XOR IP,X \ (new XOR old) Toggle bit (13)
2844 BIT #BIT13,X \ X(13) = New_RC5_command
2845 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
2847 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
2848 \ ******************************\
2849 \ RC5_ComputeNewRC5word \
2850 \ ******************************\
2852 MOV &BASE,2(PSP) \ save variable BASE before use
2853 MOV TOS,0(PSP) \ save TOS before use
2854 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
2855 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
2856 \ ******************************\
2857 \ RC5_ComputeC6bit \
2858 \ ******************************\
2859 BIT #$4000,IP \ test /C6 bit in IP
2860 0= IF BIS #$40,TOS \ set C6 bit in S
2861 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
2862 \ ******************************\
2863 \ RC5_CommandByteIsDone \ RC5_code --
2864 \ ******************************\
2866 \ ------------------------------\
2867 \ Display IR_RC5 code \
2868 \ ------------------------------\
2869 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
2870 \ ------------------------------\
2871 LO2HI \ switch from assembler to FORTH
2872 ['] LCD_CLEAR IS CR \ redirects CR
2873 ['] LCD_WrC IS EMIT \ redirects EMIT
2874 $10 BASE ! \ change BASE to hexadecimal
2875 CR ." $" 2 U.R \ print IR_RC5 code
2876 ['] (CR) IS CR \ restore CR
2877 ['] (EMIT) IS EMIT \ restore EMIT
2878 HI2LO \ switch from FORTH to assembler
2879 \ ------------------------------\
2880 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
2881 \ ------------------------------\
2882 MOV @PSP+,&BASE \ restore variable BASE
2883 RETI \ CPU is ON, GIE is OFF
2888 \ ------------------------------\
2889 \ TB0CTL = %0000 0010 1001 0100\$3C0
2890 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2891 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2892 \ -- \ID input divider \ 10 = /4
2893 \ -- \MC Mode Control \ 01 = up to TB0CCR0
2894 \ - \TBCLR TimerB Clear
2897 \ --------------------------------\\
2898 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2899 \ -- \CM Capture Mode
2904 \ --- \OUTMOD \ 011 = set/reset
2910 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
2912 \ ------------------------------\
2913 \ set TimerB to make 50kHz PWM \
2914 \ ------------------------------\
2915 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2916 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
2917 \ ------------------------------\
2918 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
2919 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
2920 \ ------------------------------\
2921 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2922 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
2923 \ ------------------------------\
2924 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2925 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
2926 \ ------------------------------\
2927 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
2928 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
2929 \ ------------------------------\
2930 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
2931 \ ------------------------------\
2932 \ set TimerB to generate PWM for LCD_Vo
2933 \ ------------------------------\
2934 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
2935 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
2936 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2937 \ ------------------------------\
2938 BIS.B #LCDVo,&LCDVo_DIR \
2939 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
2940 \ ------------------------------\
2941 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2942 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2943 \ ------------------------------\
2944 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2945 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2946 \ ------------------------------\
2947 \ WDT interval init part \
2948 \ ------------------------------\
2949 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
2950 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
2951 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
2952 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
2953 \ ------------------------------\
2955 \ ------------------------------\
2956 BIS.B #RC5,&IR_IE \ enable RC5_Int
2957 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2958 \ ------------------------------\
2959 \ init interrupt vectors
2960 \ ------------------------------\
2961 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
2962 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2963 \ ------------------------------\
2964 \ define LPM mode for ACCEPT \
2965 \ ------------------------------\
2966 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2967 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2968 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2970 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
2972 \ ------------------------------\
2974 \ ------------------------------\
2975 $03E8 20_US \ 1- wait 20 ms
2976 $03 TOP_LCD \ 2- send DB5=DB4=1
2977 $CD 20_US \ 3- wait 4,1 ms
2978 $03 TOP_LCD \ 4- send again DB5=DB4=1
2979 $5 20_US \ 5- wait 0,1 ms
2980 $03 TOP_LCD \ 6- send again again DB5=DB4=1
2981 $2 20_US \ wait 40 us = LCD cycle
2982 $02 TOP_LCD \ 7- send DB5=1 DB4=0
2983 $2 20_US \ wait 40 us = LCD cycle
2984 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2985 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2986 LCD_Clear \ 10- "LCD_Clear"
2987 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2988 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2989 LCD_Clear \ 10- "LCD_Clear"
2990 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2991 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2993 ['] (CR) IS CR \ ' (CR) is CR
2994 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
2996 ." RC5toLCD is running. Type STOP to quit"
2997 \ NOECHO \ uncomment to run this app without terminal connexion
2998 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
2999 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3003 : STOP \ stops multitasking, must to be used before downloading app
3004 ['] (WARM) IS WARM \ remove START app from FORTH init process
3005 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3014 CODE MAX \ n1 n2 -- n3 signed maximum
3015 CMP @PSP,TOS \ n2-n1
3016 S< ?GOTO FW1 \ n2<n1
3022 CODE MIN \ n1 n2 -- n3 signed minimum
3023 CMP @PSP,TOS \ n2-n1
3024 S< ?GOTO BW1 \ n2<n1
3030 : U.R \ u n -- display u unsigned in n width (n >= 2)
3032 R> OVER - 0 MAX SPACES TYPE
3036 CODE 20_US \ n -- n * 20 us
3037 BEGIN \ 3 cycles loop + 6~
3038 \ MOV #5,W \ 3 MCLK = 1 MHz
3039 \ MOV #23,W \ 3 MCLK = 4 MHz
3040 MOV #51,W \ 3 MCLK = 8 MHz
3041 \ MOV #104,W \ 3 MCLK = 16 MHz
3042 \ MOV #158,W \ 3 MCLK = 24 MHz
3043 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3053 CODE TOP_LCD \ LCD Sample
3054 \ \ if write : %xxxxWWWW --
3055 \ \ if read : -- %0000RRRR
3056 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3057 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3058 0= IF \ write LCD bits pattern
3060 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3061 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3064 THEN \ read LCD bits pattern
3067 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3068 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3074 CODE LCD_W \ byte -- write byte to LCD
3076 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3077 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3078 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3079 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3080 COLON \ high level word starts here
3081 TOP_LCD 2 20_US \ write high nibble first
3086 CODE LCD_WrC \ char -- Write Char
3087 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3092 CODE LCD_WrF \ func -- Write Fonction
3093 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3099 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3104 $02 LCD_WrF 100 20_us
3108 \ : LCD_Entry_set $04 OR LCD_WrF ;
3110 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3112 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3114 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3116 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3118 \ : LCD_Goto $80 OR LCD_WrF ;
3120 \ CODE LCD_R \ -- byte read byte from LCD
3121 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3122 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3123 \ COLON \ starts a FORTH word
3124 \ TOP_LCD 2 20_us \ -- %0000HHHH
3125 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3126 \ HI2LO \ switch from FORTH to assembler
3127 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3128 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3129 \ MOV @RSP+,IP \ restore IP saved by COLON
3134 \ CODE LCD_RdS \ -- status Read Status
3135 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3140 \ CODE LCD_RdC \ -- char Read Char
3141 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3146 \ -------------+------+------+------+------++---+---+---+---+---------+
3147 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3148 \ -------------+------+------+------+------++---+---+---+---+---------+
3149 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3150 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3151 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3152 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3153 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3154 \ -------------+------+------+------+------++---+---+---+---+---------+
3157 \ ******************************\
3158 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3159 \ ******************************\
3160 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3161 \ ------------------------------\
3162 \ define LPM mode for ACCEPT \
3163 \ ------------------------------\
3164 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3165 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3166 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3167 BIT.B #SW2,&SW2_IN \ test switch S2
3168 0= IF \ case of switch S2 pressed
3169 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
3171 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
3174 BIT.B #SW1,&SW1_IN \ test switch S1 input
3175 0= IF \ case of Switch S1 pressed
3176 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
3178 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
3182 RETI \ CPU is ON, GIE is OFF
3187 \ ------------------------------\
3188 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3189 \ ******************************\
3190 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3191 \ ******************************\
3192 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3193 \ \ SMclock = 8|16|24 MHz
3194 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
3195 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
3196 \ \ SR(9)=new Toggle bit memory (ADD on)
3197 \ ------------------------------\
3198 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
3199 \ ------------------------------\
3200 \ define LPM mode for ACCEPT \
3201 \ ------------------------------\
3202 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3203 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3204 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3205 \ ------------------------------\
3206 \ RC5_FirstStartBitHalfCycle: \
3207 \ ------------------------------\
3208 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
3209 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
3210 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
3211 MOV #1778,X \ RC5_Period in us
3212 MOV #14,W \ count of loop
3214 \ ------------------------------\
3215 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
3216 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
3217 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
3218 \ RC5_Compute_3/4_Period: \ |
3219 RRUM #1,X \ X=1/2 cycle |
3223 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
3224 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
3226 \ ------------------------------\
3227 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
3228 \ ------------------------------\
3229 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3230 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
3231 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3232 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3233 SUB #1,W \ decrement count loop
3234 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
3235 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3236 0<> WHILE \ ----> out of loop ----+
3237 \ RC5_compute_7/4_Time_out: \ |
3238 ADD X,Y \ | out of bound = 7/4 period
3239 \ RC5_WaitHalfCycleP1.2_IFG: \ |
3241 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
3242 0>= IF \ | if cycle time out of bound
3243 BIC #$30,&TA0CTL \ | stop timer_A0
3244 RETI \ | then quit to do nothing
3246 \ ------------------------------\ |
3247 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
3249 MOV &TA0R,X \ | | get new RC5_period value
3250 REPEAT \ ----> loop back --+ |
3251 \ ------------------------------\ |
3252 \ RC5_SampleEndOf: \ <---------------------+
3253 \ ------------------------------\
3254 BIC #$30,&TA0CTL \ stop timer_A0
3255 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
3256 \ ******************************\
3257 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3258 \ ******************************\
3259 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
3260 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
3261 XOR IP,X \ (new XOR old) Toggle bit (13)
3262 BIT #BIT13,X \ X(13) = New_RC5_command
3263 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
3265 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
3266 \ ******************************\
3267 \ RC5_ComputeNewRC5word \
3268 \ ******************************\
3270 MOV &BASE,2(PSP) \ save variable BASE before use
3271 MOV TOS,0(PSP) \ save TOS before use
3272 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
3273 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
3274 \ ******************************\
3275 \ RC5_ComputeC6bit \
3276 \ ******************************\
3277 BIT #$4000,IP \ test /C6 bit in IP
3278 0= IF BIS #$40,TOS \ set C6 bit in S
3279 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
3280 \ ******************************\
3281 \ RC5_CommandByteIsDone \ RC5_code --
3282 \ ******************************\
3284 \ ------------------------------\
3285 \ Display IR_RC5 code \
3286 \ ------------------------------\
3287 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
3288 \ ------------------------------\
3289 LO2HI \ switch from assembler to FORTH
3290 ['] LCD_CLEAR IS CR \ redirects CR
3291 ['] LCD_WrC IS EMIT \ redirects EMIT
3292 $10 BASE ! \ change BASE to hexadecimal
3293 CR ." $" 2 U.R \ print IR_RC5 code
3294 ['] (CR) IS CR \ restore CR
3295 ['] (EMIT) IS EMIT \ restore EMIT
3296 HI2LO \ switch from FORTH to assembler
3297 \ ------------------------------\
3298 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
3299 \ ------------------------------\
3300 MOV @PSP+,&BASE \ restore variable BASE
3301 RETI \ CPU is ON, GIE is OFF
3306 \ ------------------------------\
3307 \ TB0CTL = %0000 0010 1001 0100\$3C0
3308 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3309 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3310 \ -- \ID input divider \ 10 = /4
3311 \ -- \MC Mode Control \ 01 = up to TB0CCR0
3312 \ - \TBCLR TimerB Clear
3315 \ --------------------------------\\
3316 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3317 \ -- \CM Capture Mode
3322 \ --- \OUTMOD \ 011 = set/reset
3328 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
3330 \ ------------------------------\
3331 \ set TimerB to make 50kHz PWM \
3332 \ ------------------------------\
3333 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3334 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
3335 \ ------------------------------\
3336 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3337 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
3338 \ ------------------------------\
3339 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3340 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
3341 \ ------------------------------\
3342 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3343 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
3344 \ ------------------------------\
3345 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3346 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
3347 \ ------------------------------\
3348 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
3349 \ ------------------------------\
3350 \ set TimerB to generate PWM for LCD_Vo
3351 \ ------------------------------\
3352 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
3353 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
3354 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3355 \ ------------------------------\
3356 BIS.B #LCDVo,&LCDVo_DIR \
3357 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
3358 \ ------------------------------\
3359 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3360 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3361 \ ------------------------------\
3362 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3363 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3364 \ ------------------------------\
3365 \ WDT interval init part \
3366 \ ------------------------------\
3367 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
3368 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
3369 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
3370 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
3371 \ ------------------------------\
3373 \ ------------------------------\
3374 BIS.B #RC5,&IR_IE \ enable RC5_Int
3375 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3376 \ ------------------------------\
3377 \ init interrupt vectors
3378 \ ------------------------------\
3379 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
3380 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3381 \ ------------------------------\
3382 \ define LPM mode for ACCEPT \
3383 \ ------------------------------\
3384 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3385 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3386 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3388 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
3390 \ ------------------------------\
3392 \ ------------------------------\
3393 $03E8 20_US \ 1- wait 20 ms
3394 $03 TOP_LCD \ 2- send DB5=DB4=1
3395 $CD 20_US \ 3- wait 4,1 ms
3396 $03 TOP_LCD \ 4- send again DB5=DB4=1
3397 $5 20_US \ 5- wait 0,1 ms
3398 $03 TOP_LCD \ 6- send again again DB5=DB4=1
3399 $2 20_US \ wait 40 us = LCD cycle
3400 $02 TOP_LCD \ 7- send DB5=1 DB4=0
3401 $2 20_US \ wait 40 us = LCD cycle
3402 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3403 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3404 LCD_Clear \ 10- "LCD_Clear"
3405 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3406 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3407 LCD_Clear \ 10- "LCD_Clear"
3408 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3409 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3411 ['] (CR) IS CR \ ' (CR) is CR
3412 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
3414 ." RC5toLCD is running. Type STOP to quit"
3415 \ NOECHO \ uncomment to run this app without terminal connexion
3416 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
3417 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3421 : STOP \ stops multitasking, must to be used before downloading app
3422 ['] (WARM) IS WARM \ remove START app from FORTH init process
3423 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3432 CODE MAX \ n1 n2 -- n3 signed maximum
3433 CMP @PSP,TOS \ n2-n1
3434 S< ?GOTO FW1 \ n2<n1
3440 CODE MIN \ n1 n2 -- n3 signed minimum
3441 CMP @PSP,TOS \ n2-n1
3442 S< ?GOTO BW1 \ n2<n1
3448 : U.R \ u n -- display u unsigned in n width (n >= 2)
3450 R> OVER - 0 MAX SPACES TYPE
3454 CODE 20_US \ n -- n * 20 us
3455 BEGIN \ 3 cycles loop + 6~
3456 \ MOV #5,W \ 3 MCLK = 1 MHz
3457 \ MOV #23,W \ 3 MCLK = 4 MHz
3458 MOV #51,W \ 3 MCLK = 8 MHz
3459 \ MOV #104,W \ 3 MCLK = 16 MHz
3460 \ MOV #158,W \ 3 MCLK = 24 MHz
3461 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3471 CODE TOP_LCD \ LCD Sample
3472 \ \ if write : %xxxxWWWW --
3473 \ \ if read : -- %0000RRRR
3474 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3475 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3476 0= IF \ write LCD bits pattern
3478 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3479 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3482 THEN \ read LCD bits pattern
3485 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3486 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3492 CODE LCD_W \ byte -- write byte to LCD
3494 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3495 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3496 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3497 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3498 COLON \ high level word starts here
3499 TOP_LCD 2 20_US \ write high nibble first
3504 CODE LCD_WrC \ char -- Write Char
3505 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3510 CODE LCD_WrF \ func -- Write Fonction
3511 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3517 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3522 $02 LCD_WrF 100 20_us
3526 \ : LCD_Entry_set $04 OR LCD_WrF ;
3528 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3530 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3532 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3534 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3536 \ : LCD_Goto $80 OR LCD_WrF ;
3538 \ CODE LCD_R \ -- byte read byte from LCD
3539 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3540 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3541 \ COLON \ starts a FORTH word
3542 \ TOP_LCD 2 20_us \ -- %0000HHHH
3543 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3544 \ HI2LO \ switch from FORTH to assembler
3545 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3546 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3547 \ MOV @RSP+,IP \ restore IP saved by COLON
3552 \ CODE LCD_RdS \ -- status Read Status
3553 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3558 \ CODE LCD_RdC \ -- char Read Char
3559 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3564 \ -------------+------+------+------+------++---+---+---+---+---------+
3565 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3566 \ -------------+------+------+------+------++---+---+---+---+---------+
3567 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3568 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3569 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3570 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3571 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3572 \ -------------+------+------+------+------++---+---+---+---+---------+
3575 \ ******************************\
3576 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3577 \ ******************************\
3578 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3579 \ ------------------------------\
3580 \ define LPM mode for ACCEPT \
3581 \ ------------------------------\
3582 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3583 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3584 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3585 BIT.B #SW2,&SW2_IN \ test switch S2
3586 0= IF \ case of switch S2 pressed
3587 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
3589 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
3592 BIT.B #SW1,&SW1_IN \ test switch S1 input
3593 0= IF \ case of Switch S1 pressed
3594 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
3596 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
3600 RETI \ CPU is ON, GIE is OFF
3605 \ ------------------------------\
3606 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3607 \ ******************************\
3608 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3609 \ ******************************\
3610 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3611 \ \ SMclock = 8|16|24 MHz
3612 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
3613 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
3614 \ \ SR(9)=new Toggle bit memory (ADD on)
3615 \ ------------------------------\
3616 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
3617 \ ------------------------------\
3618 \ define LPM mode for ACCEPT \
3619 \ ------------------------------\
3620 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3621 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3622 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3623 \ ------------------------------\
3624 \ RC5_FirstStartBitHalfCycle: \
3625 \ ------------------------------\
3626 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
3627 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
3628 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
3629 MOV #1778,X \ RC5_Period in us
3630 MOV #14,W \ count of loop
3632 \ ------------------------------\
3633 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
3634 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
3635 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
3636 \ RC5_Compute_3/4_Period: \ |
3637 RRUM #1,X \ X=1/2 cycle |
3641 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
3642 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
3644 \ ------------------------------\
3645 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
3646 \ ------------------------------\
3647 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3648 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
3649 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3650 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3651 SUB #1,W \ decrement count loop
3652 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
3653 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3654 0<> WHILE \ ----> out of loop ----+
3655 \ RC5_compute_7/4_Time_out: \ |
3656 ADD X,Y \ | out of bound = 7/4 period
3657 \ RC5_WaitHalfCycleP1.2_IFG: \ |
3659 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
3660 0>= IF \ | if cycle time out of bound
3661 BIC #$30,&TA0CTL \ | stop timer_A0
3662 RETI \ | then quit to do nothing
3664 \ ------------------------------\ |
3665 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
3667 MOV &TA0R,X \ | | get new RC5_period value
3668 REPEAT \ ----> loop back --+ |
3669 \ ------------------------------\ |
3670 \ RC5_SampleEndOf: \ <---------------------+
3671 \ ------------------------------\
3672 BIC #$30,&TA0CTL \ stop timer_A0
3673 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
3674 \ ******************************\
3675 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3676 \ ******************************\
3677 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
3678 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
3679 XOR IP,X \ (new XOR old) Toggle bit (13)
3680 BIT #BIT13,X \ X(13) = New_RC5_command
3681 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
3683 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
3684 \ ******************************\
3685 \ RC5_ComputeNewRC5word \
3686 \ ******************************\
3688 MOV &BASE,2(PSP) \ save variable BASE before use
3689 MOV TOS,0(PSP) \ save TOS before use
3690 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
3691 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
3692 \ ******************************\
3693 \ RC5_ComputeC6bit \
3694 \ ******************************\
3695 BIT #$4000,IP \ test /C6 bit in IP
3696 0= IF BIS #$40,TOS \ set C6 bit in S
3697 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
3698 \ ******************************\
3699 \ RC5_CommandByteIsDone \ RC5_code --
3700 \ ******************************\
3702 \ ------------------------------\
3703 \ Display IR_RC5 code \
3704 \ ------------------------------\
3705 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
3706 \ ------------------------------\
3707 LO2HI \ switch from assembler to FORTH
3708 ['] LCD_CLEAR IS CR \ redirects CR
3709 ['] LCD_WrC IS EMIT \ redirects EMIT
3710 $10 BASE ! \ change BASE to hexadecimal
3711 CR ." $" 2 U.R \ print IR_RC5 code
3712 ['] (CR) IS CR \ restore CR
3713 ['] (EMIT) IS EMIT \ restore EMIT
3714 HI2LO \ switch from FORTH to assembler
3715 \ ------------------------------\
3716 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
3717 \ ------------------------------\
3718 MOV @PSP+,&BASE \ restore variable BASE
3719 RETI \ CPU is ON, GIE is OFF
3724 \ ------------------------------\
3725 \ TB0CTL = %0000 0010 1001 0100\$3C0
3726 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3727 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3728 \ -- \ID input divider \ 10 = /4
3729 \ -- \MC Mode Control \ 01 = up to TB0CCR0
3730 \ - \TBCLR TimerB Clear
3733 \ --------------------------------\\
3734 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3735 \ -- \CM Capture Mode
3740 \ --- \OUTMOD \ 011 = set/reset
3746 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
3748 \ ------------------------------\
3749 \ set TimerB to make 50kHz PWM \
3750 \ ------------------------------\
3751 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3752 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
3753 \ ------------------------------\
3754 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
3755 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
3756 \ ------------------------------\
3757 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3758 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
3759 \ ------------------------------\
3760 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3761 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
3762 \ ------------------------------\
3763 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
3764 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
3765 \ ------------------------------\
3766 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
3767 \ ------------------------------\
3768 \ set TimerB to generate PWM for LCD_Vo
3769 \ ------------------------------\
3770 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
3771 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
3772 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3773 \ ------------------------------\
3774 BIS.B #LCDVo,&LCDVo_DIR \
3775 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
3776 \ ------------------------------\
3777 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3778 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3779 \ ------------------------------\
3780 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3781 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3782 \ ------------------------------\
3783 \ WDT interval init part \
3784 \ ------------------------------\
3785 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
3786 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
3787 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
3788 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
3789 \ ------------------------------\
3791 \ ------------------------------\
3792 BIS.B #RC5,&IR_IE \ enable RC5_Int
3793 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3794 \ ------------------------------\
3795 \ init interrupt vectors
3796 \ ------------------------------\
3797 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
3798 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3799 \ ------------------------------\
3800 \ define LPM mode for ACCEPT \
3801 \ ------------------------------\
3802 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3803 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3804 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3806 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
3808 \ ------------------------------\
3810 \ ------------------------------\
3811 $03E8 20_US \ 1- wait 20 ms
3812 $03 TOP_LCD \ 2- send DB5=DB4=1
3813 $CD 20_US \ 3- wait 4,1 ms
3814 $03 TOP_LCD \ 4- send again DB5=DB4=1
3815 $5 20_US \ 5- wait 0,1 ms
3816 $03 TOP_LCD \ 6- send again again DB5=DB4=1
3817 $2 20_US \ wait 40 us = LCD cycle
3818 $02 TOP_LCD \ 7- send DB5=1 DB4=0
3819 $2 20_US \ wait 40 us = LCD cycle
3820 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3821 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3822 LCD_Clear \ 10- "LCD_Clear"
3823 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3824 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3825 LCD_Clear \ 10- "LCD_Clear"
3826 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3827 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3829 ['] (CR) IS CR \ ' (CR) is CR
3830 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
3832 ." RC5toLCD is running. Type STOP to quit"
3833 \ NOECHO \ uncomment to run this app without terminal connexion
3834 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
3835 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
3839 : STOP \ stops multitasking, must to be used before downloading app
3840 ['] (WARM) IS WARM \ remove START app from FORTH init process
3841 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
3850 CODE MAX \ n1 n2 -- n3 signed maximum
3851 CMP @PSP,TOS \ n2-n1
3852 S< ?GOTO FW1 \ n2<n1
3858 CODE MIN \ n1 n2 -- n3 signed minimum
3859 CMP @PSP,TOS \ n2-n1
3860 S< ?GOTO BW1 \ n2<n1
3866 : U.R \ u n -- display u unsigned in n width (n >= 2)
3868 R> OVER - 0 MAX SPACES TYPE
3872 CODE 20_US \ n -- n * 20 us
3873 BEGIN \ 3 cycles loop + 6~
3874 \ MOV #5,W \ 3 MCLK = 1 MHz
3875 \ MOV #23,W \ 3 MCLK = 4 MHz
3876 MOV #51,W \ 3 MCLK = 8 MHz
3877 \ MOV #104,W \ 3 MCLK = 16 MHz
3878 \ MOV #158,W \ 3 MCLK = 24 MHz
3879 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
3889 CODE TOP_LCD \ LCD Sample
3890 \ \ if write : %xxxxWWWW --
3891 \ \ if read : -- %0000RRRR
3892 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3893 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3894 0= IF \ write LCD bits pattern
3896 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3897 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3900 THEN \ read LCD bits pattern
3903 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3904 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3910 CODE LCD_W \ byte -- write byte to LCD
3912 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
3913 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
3914 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3915 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3916 COLON \ high level word starts here
3917 TOP_LCD 2 20_US \ write high nibble first
3922 CODE LCD_WrC \ char -- Write Char
3923 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3928 CODE LCD_WrF \ func -- Write Fonction
3929 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3935 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
3940 $02 LCD_WrF 100 20_us
3944 \ : LCD_Entry_set $04 OR LCD_WrF ;
3946 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
3948 \ : LCD_Display_Shift $10 OR LCD_WrF ;
3950 \ : LCD_Fn_Set $20 OR LCD_WrF ;
3952 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
3954 \ : LCD_Goto $80 OR LCD_WrF ;
3956 \ CODE LCD_R \ -- byte read byte from LCD
3957 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3958 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3959 \ COLON \ starts a FORTH word
3960 \ TOP_LCD 2 20_us \ -- %0000HHHH
3961 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
3962 \ HI2LO \ switch from FORTH to assembler
3963 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
3964 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
3965 \ MOV @RSP+,IP \ restore IP saved by COLON
3970 \ CODE LCD_RdS \ -- status Read Status
3971 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3976 \ CODE LCD_RdC \ -- char Read Char
3977 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3982 \ -------------+------+------+------+------++---+---+---+---+---------+
3983 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
3984 \ -------------+------+------+------+------++---+---+---+---+---------+
3985 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
3986 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
3987 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
3988 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
3989 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
3990 \ -------------+------+------+------+------++---+---+---+---+---------+
3993 \ ******************************\
3994 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3995 \ ******************************\
3996 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
3997 \ ------------------------------\
3998 \ define LPM mode for ACCEPT \
3999 \ ------------------------------\
4000 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4001 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4002 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4003 BIT.B #SW2,&SW2_IN \ test switch S2
4004 0= IF \ case of switch S2 pressed
4005 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4007 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4010 BIT.B #SW1,&SW1_IN \ test switch S1 input
4011 0= IF \ case of Switch S1 pressed
4012 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4014 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4018 RETI \ CPU is ON, GIE is OFF
4023 \ ------------------------------\
4024 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4025 \ ******************************\
4026 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4027 \ ******************************\
4028 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4029 \ \ SMclock = 8|16|24 MHz
4030 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4031 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4032 \ \ SR(9)=new Toggle bit memory (ADD on)
4033 \ ------------------------------\
4034 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4035 \ ------------------------------\
4036 \ define LPM mode for ACCEPT \
4037 \ ------------------------------\
4038 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4039 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4040 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4041 \ ------------------------------\
4042 \ RC5_FirstStartBitHalfCycle: \
4043 \ ------------------------------\
4044 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4045 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4046 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4047 MOV #1778,X \ RC5_Period in us
4048 MOV #14,W \ count of loop
4050 \ ------------------------------\
4051 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4052 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4053 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4054 \ RC5_Compute_3/4_Period: \ |
4055 RRUM #1,X \ X=1/2 cycle |
4059 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4060 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4062 \ ------------------------------\
4063 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4064 \ ------------------------------\
4065 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4066 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4067 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4068 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4069 SUB #1,W \ decrement count loop
4070 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4071 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4072 0<> WHILE \ ----> out of loop ----+
4073 \ RC5_compute_7/4_Time_out: \ |
4074 ADD X,Y \ | out of bound = 7/4 period
4075 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4077 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4078 0>= IF \ | if cycle time out of bound
4079 BIC #$30,&TA0CTL \ | stop timer_A0
4080 RETI \ | then quit to do nothing
4082 \ ------------------------------\ |
4083 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4085 MOV &TA0R,X \ | | get new RC5_period value
4086 REPEAT \ ----> loop back --+ |
4087 \ ------------------------------\ |
4088 \ RC5_SampleEndOf: \ <---------------------+
4089 \ ------------------------------\
4090 BIC #$30,&TA0CTL \ stop timer_A0
4091 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4092 \ ******************************\
4093 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4094 \ ******************************\
4095 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
4096 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4097 XOR IP,X \ (new XOR old) Toggle bit (13)
4098 BIT #BIT13,X \ X(13) = New_RC5_command
4099 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4101 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4102 \ ******************************\
4103 \ RC5_ComputeNewRC5word \
4104 \ ******************************\
4106 MOV &BASE,2(PSP) \ save variable BASE before use
4107 MOV TOS,0(PSP) \ save TOS before use
4108 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4109 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4110 \ ******************************\
4111 \ RC5_ComputeC6bit \
4112 \ ******************************\
4113 BIT #$4000,IP \ test /C6 bit in IP
4114 0= IF BIS #$40,TOS \ set C6 bit in S
4115 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4116 \ ******************************\
4117 \ RC5_CommandByteIsDone \ RC5_code --
4118 \ ******************************\
4120 \ ------------------------------\
4121 \ Display IR_RC5 code \
4122 \ ------------------------------\
4123 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4124 \ ------------------------------\
4125 LO2HI \ switch from assembler to FORTH
4126 ['] LCD_CLEAR IS CR \ redirects CR
4127 ['] LCD_WrC IS EMIT \ redirects EMIT
4128 $10 BASE ! \ change BASE to hexadecimal
4129 CR ." $" 2 U.R \ print IR_RC5 code
4130 ['] (CR) IS CR \ restore CR
4131 ['] (EMIT) IS EMIT \ restore EMIT
4132 HI2LO \ switch from FORTH to assembler
4133 \ ------------------------------\
4134 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4135 \ ------------------------------\
4136 MOV @PSP+,&BASE \ restore variable BASE
4137 RETI \ CPU is ON, GIE is OFF
4142 \ ------------------------------\
4143 \ TB0CTL = %0000 0010 1001 0100\$3C0
4144 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4145 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4146 \ -- \ID input divider \ 10 = /4
4147 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4148 \ - \TBCLR TimerB Clear
4151 \ --------------------------------\\
4152 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4153 \ -- \CM Capture Mode
4158 \ --- \OUTMOD \ 011 = set/reset
4164 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4166 \ ------------------------------\
4167 \ set TimerB to make 50kHz PWM \
4168 \ ------------------------------\
4169 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4170 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4171 \ ------------------------------\
4172 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4173 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4174 \ ------------------------------\
4175 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4176 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
4177 \ ------------------------------\
4178 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4179 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
4180 \ ------------------------------\
4181 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4182 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
4183 \ ------------------------------\
4184 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
4185 \ ------------------------------\
4186 \ set TimerB to generate PWM for LCD_Vo
4187 \ ------------------------------\
4188 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
4189 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
4190 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4191 \ ------------------------------\
4192 BIS.B #LCDVo,&LCDVo_DIR \
4193 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
4194 \ ------------------------------\
4195 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4196 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4197 \ ------------------------------\
4198 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4199 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4200 \ ------------------------------\
4201 \ WDT interval init part \
4202 \ ------------------------------\
4203 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
4204 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
4205 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
4206 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
4207 \ ------------------------------\
4209 \ ------------------------------\
4210 BIS.B #RC5,&IR_IE \ enable RC5_Int
4211 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4212 \ ------------------------------\
4213 \ init interrupt vectors
4214 \ ------------------------------\
4215 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
4216 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4217 \ ------------------------------\
4218 \ define LPM mode for ACCEPT \
4219 \ ------------------------------\
4220 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4221 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4222 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4224 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
4226 \ ------------------------------\
4228 \ ------------------------------\
4229 $03E8 20_US \ 1- wait 20 ms
4230 $03 TOP_LCD \ 2- send DB5=DB4=1
4231 $CD 20_US \ 3- wait 4,1 ms
4232 $03 TOP_LCD \ 4- send again DB5=DB4=1
4233 $5 20_US \ 5- wait 0,1 ms
4234 $03 TOP_LCD \ 6- send again again DB5=DB4=1
4235 $2 20_US \ wait 40 us = LCD cycle
4236 $02 TOP_LCD \ 7- send DB5=1 DB4=0
4237 $2 20_US \ wait 40 us = LCD cycle
4238 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4239 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4240 LCD_Clear \ 10- "LCD_Clear"
4241 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4242 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4243 LCD_Clear \ 10- "LCD_Clear"
4244 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4245 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4247 ['] (CR) IS CR \ ' (CR) is CR
4248 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
4250 ." RC5toLCD is running. Type STOP to quit"
4251 \ NOECHO \ uncomment to run this app without terminal connexion
4252 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
4253 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
4257 : STOP \ stops multitasking, must to be used before downloading app
4258 ['] (WARM) IS WARM \ remove START app from FORTH init process
4259 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
4268 CODE MAX \ n1 n2 -- n3 signed maximum
4269 CMP @PSP,TOS \ n2-n1
4270 S< ?GOTO FW1 \ n2<n1
4276 CODE MIN \ n1 n2 -- n3 signed minimum
4277 CMP @PSP,TOS \ n2-n1
4278 S< ?GOTO BW1 \ n2<n1
4284 : U.R \ u n -- display u unsigned in n width (n >= 2)
4286 R> OVER - 0 MAX SPACES TYPE
4290 CODE 20_US \ n -- n * 20 us
4291 BEGIN \ 3 cycles loop + 6~
4292 \ MOV #5,W \ 3 MCLK = 1 MHz
4293 \ MOV #23,W \ 3 MCLK = 4 MHz
4294 MOV #51,W \ 3 MCLK = 8 MHz
4295 \ MOV #104,W \ 3 MCLK = 16 MHz
4296 \ MOV #158,W \ 3 MCLK = 24 MHz
4297 BEGIN \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
4307 CODE TOP_LCD \ LCD Sample
4308 \ \ if write : %xxxxWWWW --
4309 \ \ if read : -- %0000RRRR
4310 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4311 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4312 0= IF \ write LCD bits pattern
4314 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4315 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4318 THEN \ read LCD bits pattern
4321 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4322 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4328 CODE LCD_W \ byte -- write byte to LCD
4330 MOV TOS,0(PSP) \ -- %xxxxLLLL %HHHHLLLL
4331 RRUM #4,TOS \ -- %xxxxLLLL %xxxxHHHH
4332 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4333 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4334 COLON \ high level word starts here
4335 TOP_LCD 2 20_US \ write high nibble first
4340 CODE LCD_WrC \ char -- Write Char
4341 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4346 CODE LCD_WrF \ func -- Write Fonction
4347 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4353 $01 LCD_WrF 100 20_us \ $01 LCD_WrF 80 20_us ==> bad init !
4358 $02 LCD_WrF 100 20_us
4362 \ : LCD_Entry_set $04 OR LCD_WrF ;
4364 \ : LCD_Display_Ctrl $08 OR LCD_WrF ;
4366 \ : LCD_Display_Shift $10 OR LCD_WrF ;
4368 \ : LCD_Fn_Set $20 OR LCD_WrF ;
4370 \ : LCD_CGRAM_Set $40 OR LCD_WrF ;
4372 \ : LCD_Goto $80 OR LCD_WrF ;
4374 \ CODE LCD_R \ -- byte read byte from LCD
4375 \ BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4376 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4377 \ COLON \ starts a FORTH word
4378 \ TOP_LCD 2 20_us \ -- %0000HHHH
4379 \ TOP_LCD 2 20_us \ -- %0000HHHH %0000LLLL
4380 \ HI2LO \ switch from FORTH to assembler
4381 \ RLAM #4,0(PSP) \ -- %HHHH0000 %0000LLLL
4382 \ ADD.B @PSP+,TOS \ -- %HHHHLLLL
4383 \ MOV @RSP+,IP \ restore IP saved by COLON
4388 \ CODE LCD_RdS \ -- status Read Status
4389 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4394 \ CODE LCD_RdC \ -- char Read Char
4395 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4400 \ -------------+------+------+------+------++---+---+---+---+---------+
4401 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
4402 \ -------------+------+------+------+------++---+---+---+---+---------+
4403 \ LPM0 = $18 | 0 | 0 | 0 | 1 || 1 | x | x | x | 180uA | default mode
4404 \ LPM1 = $58 | 0 | 1 | 0 | 1 || 1 | x | x | x | | same mode as LPM0
4405 \ LPM2 = $98 | 1 | 0 | 0 | 1 || 1 | x | x | x | 60uA |
4406 \ LPM3 = $D8 | 1 | 1 | 0 | 1 || 1 | x | x | x | 10uA | 32768Hz XTAL is running
4407 \ LPM4 = $F8 | 1 | 1 | 1 | 1 || 1 | x | x | x | 6uA |
4408 \ -------------+------+------+------+------++---+---+---+---+---------+
4411 \ ******************************\
4412 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4413 \ ******************************\
4414 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR to force fall down to LPM mode
4415 \ ------------------------------\
4416 \ define LPM mode for ACCEPT \
4417 \ ------------------------------\
4418 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4419 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4420 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4421 BIT.B #SW2,&SW2_IN \ test switch S2
4422 0= IF \ case of switch S2 pressed
4423 CMP #38,&TB0CCR2 \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
4425 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
4428 BIT.B #SW1,&SW1_IN \ test switch S1 input
4429 0= IF \ case of Switch S1 pressed
4430 CMP #7,&TB0CCR2 \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
4432 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
4436 RETI \ CPU is ON, GIE is OFF
4441 \ ------------------------------\
4442 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4443 \ ******************************\
4444 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4445 \ ******************************\
4446 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4447 \ \ SMclock = 8|16|24 MHz
4448 \ \ use : BASE,TOS,IP,W,X,Y, TA0 timer, TA0R register
4449 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
4450 \ \ SR(9)=new Toggle bit memory (ADD on)
4451 \ ------------------------------\
4452 BIC #$F8,0(RSP) \ CPU is ON and GIE is OFF in retiSR to force fall down to LPM0_LOOP
4453 \ ------------------------------\
4454 \ define LPM mode for ACCEPT \
4455 \ ------------------------------\
4456 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4457 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4458 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4459 \ ------------------------------\
4460 \ RC5_FirstStartBitHalfCycle: \
4461 \ ------------------------------\
4462 MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
4463 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register (16 MHZ)
4464 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register (24 MHZ)
4465 MOV #1778,X \ RC5_Period in us
4466 MOV #14,W \ count of loop
4468 \ ------------------------------\
4469 \ RC5_TopSynchro: \ <--- loop back ---+ with readjusted RC5_Period
4470 \ ------------------------------\ | here, we are just after 1/2 RC5_cycle
4471 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 : 1us time interval,free running,clear TA0_IFG and TA0R
4472 \ RC5_Compute_3/4_Period: \ |
4473 RRUM #1,X \ X=1/2 cycle |
4477 \ RC5_Wait_1_1/4 \ wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle+1
4478 BEGIN CMP Y,&TA0R \ CMP &TA0R with 3/4 cycle value
4480 \ ------------------------------\
4481 \ RC5_Sample: \ at 5/4 cycle, we can sample RC5_input, ST2/C6 bit first
4482 \ ------------------------------\
4483 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4484 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
4485 MOV &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4486 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4487 SUB #1,W \ decrement count loop
4488 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
4489 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4490 0<> WHILE \ ----> out of loop ----+
4491 \ RC5_compute_7/4_Time_out: \ |
4492 ADD X,Y \ | out of bound = 7/4 period
4493 \ RC5_WaitHalfCycleP1.2_IFG: \ |
4495 CMP Y,&TA0R \ | TA0R = 5/4 cycle test
4496 0>= IF \ | if cycle time out of bound
4497 BIC #$30,&TA0CTL \ | stop timer_A0
4498 RETI \ | then quit to do nothing
4500 \ ------------------------------\ |
4501 BIT.B #RC5,&IR_IFG \ ^ | test P1.2_IFG
4503 MOV &TA0R,X \ | | get new RC5_period value
4504 REPEAT \ ----> loop back --+ |
4505 \ ------------------------------\ |
4506 \ RC5_SampleEndOf: \ <---------------------+
4507 \ ------------------------------\
4508 BIC #$30,&TA0CTL \ stop timer_A0
4509 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2|A1 A0 C5 C4 C3 C2 C1 C0 1 0
4510 \ ******************************\
4511 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4512 \ ******************************\
4513 MOV @RSP,X \ retiSR(9) = old UF9 = old RC5 toggle bit
4514 RLAM #4,X \ retiSR(11,10,9)= X(11,10,9) --> X(15,14,13)
4515 XOR IP,X \ (new XOR old) Toggle bit (13)
4516 BIT #BIT13,X \ X(13) = New_RC5_command
4517 0= IF RETI \ case of repeated RC5_command : RETI without SR(9) change
4519 XOR #UF9,0(RSP) \ change Toggle bit memory, UserFlag1 = SR(9) = 1
4520 \ ******************************\
4521 \ RC5_ComputeNewRC5word \
4522 \ ******************************\
4524 MOV &BASE,2(PSP) \ save variable BASE before use
4525 MOV TOS,0(PSP) \ save TOS before use
4526 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 0 0
4527 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
4528 \ ******************************\
4529 \ RC5_ComputeC6bit \
4530 \ ******************************\
4531 BIT #$4000,IP \ test /C6 bit in IP
4532 0= IF BIS #$40,TOS \ set C6 bit in S
4533 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
4534 \ ******************************\
4535 \ RC5_CommandByteIsDone \ RC5_code --
4536 \ ******************************\
4538 \ ------------------------------\
4539 \ Display IR_RC5 code \
4540 \ ------------------------------\
4541 \ BIS.B #LED1,&LED1_OUT \ switch ON LED1, comment if no LED
4542 \ ------------------------------\
4543 LO2HI \ switch from assembler to FORTH
4544 ['] LCD_CLEAR IS CR \ redirects CR
4545 ['] LCD_WrC IS EMIT \ redirects EMIT
4546 $10 BASE ! \ change BASE to hexadecimal
4547 CR ." $" 2 U.R \ print IR_RC5 code
4548 ['] (CR) IS CR \ restore CR
4549 ['] (EMIT) IS EMIT \ restore EMIT
4550 HI2LO \ switch from FORTH to assembler
4551 \ ------------------------------\
4552 \ BIC.B #LED1,&LED1_OUT \ switch OFF LED1, comment if no LED
4553 \ ------------------------------\
4554 MOV @PSP+,&BASE \ restore variable BASE
4555 RETI \ CPU is ON, GIE is OFF
4560 \ ------------------------------\
4561 \ TB0CTL = %0000 0010 1001 0100\$3C0
4562 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4563 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4564 \ -- \ID input divider \ 10 = /4
4565 \ -- \MC Mode Control \ 01 = up to TB0CCR0
4566 \ - \TBCLR TimerB Clear
4569 \ --------------------------------\\
4570 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4571 \ -- \CM Capture Mode
4576 \ --- \OUTMOD \ 011 = set/reset
4582 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
4584 \ ------------------------------\
4585 \ set TimerB to make 50kHz PWM \
4586 \ ------------------------------\
4587 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4588 \ MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
4589 \ ------------------------------\
4590 \ MOV #%1000010100,&TB0CTL \ SMCLK/1, up mode, clear timer, no int
4591 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (4 MHZ)
4592 \ ------------------------------\
4593 MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4594 MOV #0,&TB0EX0 \ predivide by 1 in TB0EX0 register (8 MHZ)
4595 \ ------------------------------\
4596 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4597 \ MOV #1,&TB0EX0 \ predivide by 2 in TB0EX0 register (16 MHZ)
4598 \ ------------------------------\
4599 \ MOV #%1010010100,&TB0CTL \ SMCLK/4, up mode, clear timer, no int
4600 \ MOV #2,&TB0EX0 \ predivide by 3 in TB0EX0 register (24 MHZ)
4601 \ ------------------------------\
4602 MOV #40,&TB0CCR0 \ 40*0.5us=20us (40us @ 1MHz)
4603 \ ------------------------------\
4604 \ set TimerB to generate PWM for LCD_Vo
4605 \ ------------------------------\
4606 MOV #%1100000,&TB0CCTL2 \ output mode = set/reset \ clear CCIFG
4607 \ MOV #20,&TB0CCR2 \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
4608 MOV #25,&TB0CCR2 \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4609 \ ------------------------------\
4610 BIS.B #LCDVo,&LCDVo_DIR \
4611 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2 TB0.2
4612 \ ------------------------------\
4613 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4614 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4615 \ ------------------------------\
4616 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4617 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4618 \ ------------------------------\
4619 \ WDT interval init part \
4620 \ ------------------------------\
4621 MOV #$5A5E,&WDTCTL \ init WDT VLOCLK source ~10kHz /2^9 (50 ms), interval mode
4622 \ MOV #$5A3D,&WDTCTL \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
4623 \ MOV #$5A5D,&WDTCTL \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
4624 BIS #1,&SFRIE1 \ enable WDT interval mode interrupt in SFRIE
4625 \ ------------------------------\
4627 \ ------------------------------\
4628 BIS.B #RC5,&IR_IE \ enable RC5_Int
4629 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4630 \ ------------------------------\
4631 \ init interrupt vectors
4632 \ ------------------------------\
4633 MOV #WDT_INT,&WDT_Vec \ init WDT interval vector interrupt
4634 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4635 \ ------------------------------\
4636 \ define LPM mode for ACCEPT \
4637 \ ------------------------------\
4638 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4639 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4640 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4642 LO2HI \ no need to push IP because (WARM) resets the Return Stack !
4644 \ ------------------------------\
4646 \ ------------------------------\
4647 $03E8 20_US \ 1- wait 20 ms
4648 $03 TOP_LCD \ 2- send DB5=DB4=1
4649 $CD 20_US \ 3- wait 4,1 ms
4650 $03 TOP_LCD \ 4- send again DB5=DB4=1
4651 $5 20_US \ 5- wait 0,1 ms
4652 $03 TOP_LCD \ 6- send again again DB5=DB4=1
4653 $2 20_US \ wait 40 us = LCD cycle
4654 $02 TOP_LCD \ 7- send DB5=1 DB4=0
4655 $2 20_US \ wait 40 us = LCD cycle
4656 $28 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4657 $08 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4658 LCD_Clear \ 10- "LCD_Clear"
4659 $06 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4660 $0C LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4661 LCD_Clear \ 10- "LCD_Clear"
4662 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4663 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4665 ['] (CR) IS CR \ ' (CR) is CR
4666 ['] (EMIT) IS EMIT \ ' (EMIT) is EMIT
4668 ." RC5toLCD is running. Type STOP to quit"
4669 \ NOECHO \ uncomment to run this app without terminal connexion
4670 LIT RECURSE IS WARM \ insert this START routine between WARM and (WARM)...
4671 (WARM) \ ...and continue with (WARM) (very, very usefull after COLD or RESET !:-)
4675 : STOP \ stops multitasking, must to be used before downloading app
4676 ['] (WARM) IS WARM \ remove START app from FORTH init process
4677 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
4686 PWR_HERE ; this app is protected against power ON/OFF,